diff options
-rw-r--r-- | drivers/net/macvtap.c | 2 | ||||
-rw-r--r-- | drivers/net/tun.c | 2 | ||||
-rw-r--r-- | include/net/sock.h | 3 | ||||
-rw-r--r-- | net/core/sock.c | 100 | ||||
-rw-r--r-- | net/packet/af_packet.c | 2 | ||||
-rw-r--r-- | net/unix/af_unix.c | 6 |
6 files changed, 60 insertions, 55 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 182364abfa35..8f6056d9ba97 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -524,7 +524,7 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad, | |||
524 | linear = len; | 524 | linear = len; |
525 | 525 | ||
526 | skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, | 526 | skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, |
527 | err); | 527 | err, 0); |
528 | if (!skb) | 528 | if (!skb) |
529 | return NULL; | 529 | return NULL; |
530 | 530 | ||
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index b1630479d4a1..978d8654b14a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -949,7 +949,7 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, | |||
949 | linear = len; | 949 | linear = len; |
950 | 950 | ||
951 | skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, | 951 | skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, |
952 | &err); | 952 | &err, 0); |
953 | if (!skb) | 953 | if (!skb) |
954 | return ERR_PTR(err); | 954 | return ERR_PTR(err); |
955 | 955 | ||
diff --git a/include/net/sock.h b/include/net/sock.h index ab6a8b75207e..e4bbcbfd07ea 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1539,7 +1539,8 @@ extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk, | |||
1539 | unsigned long header_len, | 1539 | unsigned long header_len, |
1540 | unsigned long data_len, | 1540 | unsigned long data_len, |
1541 | int noblock, | 1541 | int noblock, |
1542 | int *errcode); | 1542 | int *errcode, |
1543 | int max_page_order); | ||
1543 | extern void *sock_kmalloc(struct sock *sk, int size, | 1544 | extern void *sock_kmalloc(struct sock *sk, int size, |
1544 | gfp_t priority); | 1545 | gfp_t priority); |
1545 | extern void sock_kfree_s(struct sock *sk, void *mem, int size); | 1546 | extern void sock_kfree_s(struct sock *sk, void *mem, int size); |
diff --git a/net/core/sock.c b/net/core/sock.c index 83667de45ec9..5b6beba494a3 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1741,24 +1741,23 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo) | |||
1741 | 1741 | ||
1742 | struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | 1742 | struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, |
1743 | unsigned long data_len, int noblock, | 1743 | unsigned long data_len, int noblock, |
1744 | int *errcode) | 1744 | int *errcode, int max_page_order) |
1745 | { | 1745 | { |
1746 | struct sk_buff *skb; | 1746 | struct sk_buff *skb = NULL; |
1747 | unsigned long chunk; | ||
1747 | gfp_t gfp_mask; | 1748 | gfp_t gfp_mask; |
1748 | long timeo; | 1749 | long timeo; |
1749 | int err; | 1750 | int err; |
1750 | int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 1751 | int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |
1752 | struct page *page; | ||
1753 | int i; | ||
1751 | 1754 | ||
1752 | err = -EMSGSIZE; | 1755 | err = -EMSGSIZE; |
1753 | if (npages > MAX_SKB_FRAGS) | 1756 | if (npages > MAX_SKB_FRAGS) |
1754 | goto failure; | 1757 | goto failure; |
1755 | 1758 | ||
1756 | gfp_mask = sk->sk_allocation; | ||
1757 | if (gfp_mask & __GFP_WAIT) | ||
1758 | gfp_mask |= __GFP_REPEAT; | ||
1759 | |||
1760 | timeo = sock_sndtimeo(sk, noblock); | 1759 | timeo = sock_sndtimeo(sk, noblock); |
1761 | while (1) { | 1760 | while (!skb) { |
1762 | err = sock_error(sk); | 1761 | err = sock_error(sk); |
1763 | if (err != 0) | 1762 | if (err != 0) |
1764 | goto failure; | 1763 | goto failure; |
@@ -1767,50 +1766,52 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | |||
1767 | if (sk->sk_shutdown & SEND_SHUTDOWN) | 1766 | if (sk->sk_shutdown & SEND_SHUTDOWN) |
1768 | goto failure; | 1767 | goto failure; |
1769 | 1768 | ||
1770 | if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { | 1769 | if (atomic_read(&sk->sk_wmem_alloc) >= sk->sk_sndbuf) { |
1771 | skb = alloc_skb(header_len, gfp_mask); | 1770 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); |
1772 | if (skb) { | 1771 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
1773 | int i; | 1772 | err = -EAGAIN; |
1774 | 1773 | if (!timeo) | |
1775 | /* No pages, we're done... */ | 1774 | goto failure; |
1776 | if (!data_len) | 1775 | if (signal_pending(current)) |
1777 | break; | 1776 | goto interrupted; |
1778 | 1777 | timeo = sock_wait_for_wmem(sk, timeo); | |
1779 | skb->truesize += data_len; | 1778 | continue; |
1780 | skb_shinfo(skb)->nr_frags = npages; | 1779 | } |
1781 | for (i = 0; i < npages; i++) { | ||
1782 | struct page *page; | ||
1783 | |||
1784 | page = alloc_pages(sk->sk_allocation, 0); | ||
1785 | if (!page) { | ||
1786 | err = -ENOBUFS; | ||
1787 | skb_shinfo(skb)->nr_frags = i; | ||
1788 | kfree_skb(skb); | ||
1789 | goto failure; | ||
1790 | } | ||
1791 | |||
1792 | __skb_fill_page_desc(skb, i, | ||
1793 | page, 0, | ||
1794 | (data_len >= PAGE_SIZE ? | ||
1795 | PAGE_SIZE : | ||
1796 | data_len)); | ||
1797 | data_len -= PAGE_SIZE; | ||
1798 | } | ||
1799 | 1780 | ||
1800 | /* Full success... */ | 1781 | err = -ENOBUFS; |
1801 | break; | 1782 | gfp_mask = sk->sk_allocation; |
1802 | } | 1783 | if (gfp_mask & __GFP_WAIT) |
1803 | err = -ENOBUFS; | 1784 | gfp_mask |= __GFP_REPEAT; |
1785 | |||
1786 | skb = alloc_skb(header_len, gfp_mask); | ||
1787 | if (!skb) | ||
1804 | goto failure; | 1788 | goto failure; |
1789 | |||
1790 | skb->truesize += data_len; | ||
1791 | |||
1792 | for (i = 0; npages > 0; i++) { | ||
1793 | int order = max_page_order; | ||
1794 | |||
1795 | while (order) { | ||
1796 | if (npages >= 1 << order) { | ||
1797 | page = alloc_pages(sk->sk_allocation | | ||
1798 | __GFP_COMP | __GFP_NOWARN, | ||
1799 | order); | ||
1800 | if (page) | ||
1801 | goto fill_page; | ||
1802 | } | ||
1803 | order--; | ||
1804 | } | ||
1805 | page = alloc_page(sk->sk_allocation); | ||
1806 | if (!page) | ||
1807 | goto failure; | ||
1808 | fill_page: | ||
1809 | chunk = min_t(unsigned long, data_len, | ||
1810 | PAGE_SIZE << order); | ||
1811 | skb_fill_page_desc(skb, i, page, 0, chunk); | ||
1812 | data_len -= chunk; | ||
1813 | npages -= 1 << order; | ||
1805 | } | 1814 | } |
1806 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | ||
1807 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
1808 | err = -EAGAIN; | ||
1809 | if (!timeo) | ||
1810 | goto failure; | ||
1811 | if (signal_pending(current)) | ||
1812 | goto interrupted; | ||
1813 | timeo = sock_wait_for_wmem(sk, timeo); | ||
1814 | } | 1815 | } |
1815 | 1816 | ||
1816 | skb_set_owner_w(skb, sk); | 1817 | skb_set_owner_w(skb, sk); |
@@ -1819,6 +1820,7 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | |||
1819 | interrupted: | 1820 | interrupted: |
1820 | err = sock_intr_errno(timeo); | 1821 | err = sock_intr_errno(timeo); |
1821 | failure: | 1822 | failure: |
1823 | kfree_skb(skb); | ||
1822 | *errcode = err; | 1824 | *errcode = err; |
1823 | return NULL; | 1825 | return NULL; |
1824 | } | 1826 | } |
@@ -1827,7 +1829,7 @@ EXPORT_SYMBOL(sock_alloc_send_pskb); | |||
1827 | struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, | 1829 | struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, |
1828 | int noblock, int *errcode) | 1830 | int noblock, int *errcode) |
1829 | { | 1831 | { |
1830 | return sock_alloc_send_pskb(sk, size, 0, noblock, errcode); | 1832 | return sock_alloc_send_pskb(sk, size, 0, noblock, errcode, 0); |
1831 | } | 1833 | } |
1832 | EXPORT_SYMBOL(sock_alloc_send_skb); | 1834 | EXPORT_SYMBOL(sock_alloc_send_skb); |
1833 | 1835 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4cb28a7f639b..6c53dd9f5ccc 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2181,7 +2181,7 @@ static struct sk_buff *packet_alloc_skb(struct sock *sk, size_t prepad, | |||
2181 | linear = len; | 2181 | linear = len; |
2182 | 2182 | ||
2183 | skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, | 2183 | skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, |
2184 | err); | 2184 | err, 0); |
2185 | if (!skb) | 2185 | if (!skb) |
2186 | return NULL; | 2186 | return NULL; |
2187 | 2187 | ||
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 99dc760cdd95..fee9e3397cd1 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -1479,7 +1479,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1479 | MAX_SKB_FRAGS * PAGE_SIZE); | 1479 | MAX_SKB_FRAGS * PAGE_SIZE); |
1480 | 1480 | ||
1481 | skb = sock_alloc_send_pskb(sk, len - data_len, data_len, | 1481 | skb = sock_alloc_send_pskb(sk, len - data_len, data_len, |
1482 | msg->msg_flags & MSG_DONTWAIT, &err); | 1482 | msg->msg_flags & MSG_DONTWAIT, &err, |
1483 | PAGE_ALLOC_COSTLY_ORDER); | ||
1483 | if (skb == NULL) | 1484 | if (skb == NULL) |
1484 | goto out; | 1485 | goto out; |
1485 | 1486 | ||
@@ -1651,7 +1652,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1651 | data_len = max_t(int, 0, size - SKB_MAX_HEAD(0)); | 1652 | data_len = max_t(int, 0, size - SKB_MAX_HEAD(0)); |
1652 | 1653 | ||
1653 | skb = sock_alloc_send_pskb(sk, size - data_len, data_len, | 1654 | skb = sock_alloc_send_pskb(sk, size - data_len, data_len, |
1654 | msg->msg_flags & MSG_DONTWAIT, &err); | 1655 | msg->msg_flags & MSG_DONTWAIT, &err, |
1656 | get_order(UNIX_SKB_FRAGS_SZ)); | ||
1655 | if (!skb) | 1657 | if (!skb) |
1656 | goto out_err; | 1658 | goto out_err; |
1657 | 1659 | ||