aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/sock.c')
-rw-r--r--net/core/sock.c49
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}
1745EXPORT_SYMBOL(sock_alloc_send_skb); 1745EXPORT_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
1750bool 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}
1784EXPORT_SYMBOL(sk_page_frag_refill);
1785
1747static void __lock_sock(struct sock *sk) 1786static 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}
2422EXPORT_SYMBOL(sk_common_release); 2467EXPORT_SYMBOL(sk_common_release);