diff options
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 2693f7649222..727114cd6f7e 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1744,6 +1744,45 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, | |||
1744 | } | 1744 | } |
1745 | EXPORT_SYMBOL(sock_alloc_send_skb); | 1745 | EXPORT_SYMBOL(sock_alloc_send_skb); |
1746 | 1746 | ||
1747 | /* On 32bit arches, an skb frag is limited to 2^15 */ | ||
1748 | #define SKB_FRAG_PAGE_ORDER get_order(32768) | ||
1749 | |||
1750 | bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag) | ||
1751 | { | ||
1752 | int order; | ||
1753 | |||
1754 | if (pfrag->page) { | ||
1755 | if (atomic_read(&pfrag->page->_count) == 1) { | ||
1756 | pfrag->offset = 0; | ||
1757 | return true; | ||
1758 | } | ||
1759 | if (pfrag->offset < pfrag->size) | ||
1760 | return true; | ||
1761 | put_page(pfrag->page); | ||
1762 | } | ||
1763 | |||
1764 | /* We restrict high order allocations to users that can afford to wait */ | ||
1765 | order = (sk->sk_allocation & __GFP_WAIT) ? SKB_FRAG_PAGE_ORDER : 0; | ||
1766 | |||
1767 | do { | ||
1768 | gfp_t gfp = sk->sk_allocation; | ||
1769 | |||
1770 | if (order) | ||
1771 | gfp |= __GFP_COMP | __GFP_NOWARN; | ||
1772 | pfrag->page = alloc_pages(gfp, order); | ||
1773 | if (likely(pfrag->page)) { | ||
1774 | pfrag->offset = 0; | ||
1775 | pfrag->size = PAGE_SIZE << order; | ||
1776 | return true; | ||
1777 | } | ||
1778 | } while (--order >= 0); | ||
1779 | |||
1780 | sk_enter_memory_pressure(sk); | ||
1781 | sk_stream_moderate_sndbuf(sk); | ||
1782 | return false; | ||
1783 | } | ||
1784 | EXPORT_SYMBOL(sk_page_frag_refill); | ||
1785 | |||
1747 | static void __lock_sock(struct sock *sk) | 1786 | static void __lock_sock(struct sock *sk) |
1748 | __releases(&sk->sk_lock.slock) | 1787 | __releases(&sk->sk_lock.slock) |
1749 | __acquires(&sk->sk_lock.slock) | 1788 | __acquires(&sk->sk_lock.slock) |
@@ -2173,8 +2212,8 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
2173 | sk->sk_error_report = sock_def_error_report; | 2212 | sk->sk_error_report = sock_def_error_report; |
2174 | sk->sk_destruct = sock_def_destruct; | 2213 | sk->sk_destruct = sock_def_destruct; |
2175 | 2214 | ||
2176 | sk->sk_sndmsg_page = NULL; | 2215 | sk->sk_frag.page = NULL; |
2177 | sk->sk_sndmsg_off = 0; | 2216 | sk->sk_frag.offset = 0; |
2178 | sk->sk_peek_off = -1; | 2217 | sk->sk_peek_off = -1; |
2179 | 2218 | ||
2180 | sk->sk_peer_pid = NULL; | 2219 | sk->sk_peer_pid = NULL; |
@@ -2417,6 +2456,12 @@ void sk_common_release(struct sock *sk) | |||
2417 | xfrm_sk_free_policy(sk); | 2456 | xfrm_sk_free_policy(sk); |
2418 | 2457 | ||
2419 | sk_refcnt_debug_release(sk); | 2458 | sk_refcnt_debug_release(sk); |
2459 | |||
2460 | if (sk->sk_frag.page) { | ||
2461 | put_page(sk->sk_frag.page); | ||
2462 | sk->sk_frag.page = NULL; | ||
2463 | } | ||
2464 | |||
2420 | sock_put(sk); | 2465 | sock_put(sk); |
2421 | } | 2466 | } |
2422 | EXPORT_SYMBOL(sk_common_release); | 2467 | EXPORT_SYMBOL(sk_common_release); |