diff options
Diffstat (limited to 'net/unix')
| -rw-r--r-- | net/unix/af_unix.c | 70 |
1 files changed, 34 insertions, 36 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index c4ce243824bb..86de99ad2976 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 | ||
| @@ -1596,6 +1597,10 @@ out: | |||
| 1596 | return err; | 1597 | return err; |
| 1597 | } | 1598 | } |
| 1598 | 1599 | ||
| 1600 | /* We use paged skbs for stream sockets, and limit occupancy to 32768 | ||
| 1601 | * bytes, and a minimun of a full page. | ||
| 1602 | */ | ||
| 1603 | #define UNIX_SKB_FRAGS_SZ (PAGE_SIZE << get_order(32768)) | ||
| 1599 | 1604 | ||
| 1600 | static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | 1605 | static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, |
| 1601 | struct msghdr *msg, size_t len) | 1606 | struct msghdr *msg, size_t len) |
| @@ -1609,6 +1614,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1609 | struct scm_cookie tmp_scm; | 1614 | struct scm_cookie tmp_scm; |
| 1610 | bool fds_sent = false; | 1615 | bool fds_sent = false; |
| 1611 | int max_level; | 1616 | int max_level; |
| 1617 | int data_len; | ||
| 1612 | 1618 | ||
| 1613 | if (NULL == siocb->scm) | 1619 | if (NULL == siocb->scm) |
| 1614 | siocb->scm = &tmp_scm; | 1620 | siocb->scm = &tmp_scm; |
| @@ -1635,40 +1641,22 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1635 | goto pipe_err; | 1641 | goto pipe_err; |
| 1636 | 1642 | ||
| 1637 | while (sent < len) { | 1643 | while (sent < len) { |
| 1638 | /* | 1644 | size = len - sent; |
| 1639 | * Optimisation for the fact that under 0.01% of X | ||
| 1640 | * messages typically need breaking up. | ||
| 1641 | */ | ||
| 1642 | |||
| 1643 | size = len-sent; | ||
| 1644 | 1645 | ||
| 1645 | /* Keep two messages in the pipe so it schedules better */ | 1646 | /* Keep two messages in the pipe so it schedules better */ |
| 1646 | if (size > ((sk->sk_sndbuf >> 1) - 64)) | 1647 | size = min_t(int, size, (sk->sk_sndbuf >> 1) - 64); |
| 1647 | size = (sk->sk_sndbuf >> 1) - 64; | ||
| 1648 | 1648 | ||
| 1649 | if (size > SKB_MAX_ALLOC) | 1649 | /* allow fallback to order-0 allocations */ |
| 1650 | size = SKB_MAX_ALLOC; | 1650 | size = min_t(int, size, SKB_MAX_HEAD(0) + UNIX_SKB_FRAGS_SZ); |
| 1651 | |||
| 1652 | /* | ||
| 1653 | * Grab a buffer | ||
| 1654 | */ | ||
| 1655 | 1651 | ||
| 1656 | skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT, | 1652 | data_len = max_t(int, 0, size - SKB_MAX_HEAD(0)); |
| 1657 | &err); | ||
| 1658 | 1653 | ||
| 1659 | if (skb == NULL) | 1654 | skb = sock_alloc_send_pskb(sk, size - data_len, data_len, |
| 1655 | msg->msg_flags & MSG_DONTWAIT, &err, | ||
| 1656 | get_order(UNIX_SKB_FRAGS_SZ)); | ||
| 1657 | if (!skb) | ||
| 1660 | goto out_err; | 1658 | goto out_err; |
| 1661 | 1659 | ||
| 1662 | /* | ||
| 1663 | * If you pass two values to the sock_alloc_send_skb | ||
| 1664 | * it tries to grab the large buffer with GFP_NOFS | ||
| 1665 | * (which can fail easily), and if it fails grab the | ||
| 1666 | * fallback size buffer which is under a page and will | ||
| 1667 | * succeed. [Alan] | ||
| 1668 | */ | ||
| 1669 | size = min_t(int, size, skb_tailroom(skb)); | ||
| 1670 | |||
| 1671 | |||
| 1672 | /* Only send the fds in the first buffer */ | 1660 | /* Only send the fds in the first buffer */ |
| 1673 | err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); | 1661 | err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); |
| 1674 | if (err < 0) { | 1662 | if (err < 0) { |
| @@ -1678,7 +1666,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1678 | max_level = err + 1; | 1666 | max_level = err + 1; |
| 1679 | fds_sent = true; | 1667 | fds_sent = true; |
| 1680 | 1668 | ||
| 1681 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); | 1669 | skb_put(skb, size - data_len); |
| 1670 | skb->data_len = data_len; | ||
| 1671 | skb->len = size; | ||
| 1672 | err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, | ||
| 1673 | sent, size); | ||
| 1682 | if (err) { | 1674 | if (err) { |
| 1683 | kfree_skb(skb); | 1675 | kfree_skb(skb); |
| 1684 | goto out_err; | 1676 | goto out_err; |
| @@ -1890,6 +1882,11 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, | |||
| 1890 | return timeo; | 1882 | return timeo; |
| 1891 | } | 1883 | } |
| 1892 | 1884 | ||
| 1885 | static unsigned int unix_skb_len(const struct sk_buff *skb) | ||
| 1886 | { | ||
| 1887 | return skb->len - UNIXCB(skb).consumed; | ||
| 1888 | } | ||
| 1889 | |||
| 1893 | static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | 1890 | static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, |
| 1894 | struct msghdr *msg, size_t size, | 1891 | struct msghdr *msg, size_t size, |
| 1895 | int flags) | 1892 | int flags) |
| @@ -1977,8 +1974,8 @@ again: | |||
| 1977 | } | 1974 | } |
| 1978 | 1975 | ||
| 1979 | skip = sk_peek_offset(sk, flags); | 1976 | skip = sk_peek_offset(sk, flags); |
| 1980 | while (skip >= skb->len) { | 1977 | while (skip >= unix_skb_len(skb)) { |
| 1981 | skip -= skb->len; | 1978 | skip -= unix_skb_len(skb); |
| 1982 | last = skb; | 1979 | last = skb; |
| 1983 | skb = skb_peek_next(skb, &sk->sk_receive_queue); | 1980 | skb = skb_peek_next(skb, &sk->sk_receive_queue); |
| 1984 | if (!skb) | 1981 | if (!skb) |
| @@ -2005,8 +2002,9 @@ again: | |||
| 2005 | sunaddr = NULL; | 2002 | sunaddr = NULL; |
| 2006 | } | 2003 | } |
| 2007 | 2004 | ||
| 2008 | chunk = min_t(unsigned int, skb->len - skip, size); | 2005 | chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size); |
| 2009 | if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) { | 2006 | if (skb_copy_datagram_iovec(skb, UNIXCB(skb).consumed + skip, |
| 2007 | msg->msg_iov, chunk)) { | ||
| 2010 | if (copied == 0) | 2008 | if (copied == 0) |
| 2011 | copied = -EFAULT; | 2009 | copied = -EFAULT; |
| 2012 | break; | 2010 | break; |
| @@ -2016,14 +2014,14 @@ again: | |||
| 2016 | 2014 | ||
| 2017 | /* Mark read part of skb as used */ | 2015 | /* Mark read part of skb as used */ |
| 2018 | if (!(flags & MSG_PEEK)) { | 2016 | if (!(flags & MSG_PEEK)) { |
| 2019 | skb_pull(skb, chunk); | 2017 | UNIXCB(skb).consumed += chunk; |
| 2020 | 2018 | ||
| 2021 | sk_peek_offset_bwd(sk, chunk); | 2019 | sk_peek_offset_bwd(sk, chunk); |
| 2022 | 2020 | ||
| 2023 | if (UNIXCB(skb).fp) | 2021 | if (UNIXCB(skb).fp) |
| 2024 | unix_detach_fds(siocb->scm, skb); | 2022 | unix_detach_fds(siocb->scm, skb); |
| 2025 | 2023 | ||
| 2026 | if (skb->len) | 2024 | if (unix_skb_len(skb)) |
| 2027 | break; | 2025 | break; |
| 2028 | 2026 | ||
| 2029 | skb_unlink(skb, &sk->sk_receive_queue); | 2027 | skb_unlink(skb, &sk->sk_receive_queue); |
| @@ -2107,7 +2105,7 @@ long unix_inq_len(struct sock *sk) | |||
| 2107 | if (sk->sk_type == SOCK_STREAM || | 2105 | if (sk->sk_type == SOCK_STREAM || |
| 2108 | sk->sk_type == SOCK_SEQPACKET) { | 2106 | sk->sk_type == SOCK_SEQPACKET) { |
| 2109 | skb_queue_walk(&sk->sk_receive_queue, skb) | 2107 | skb_queue_walk(&sk->sk_receive_queue, skb) |
| 2110 | amount += skb->len; | 2108 | amount += unix_skb_len(skb); |
| 2111 | } else { | 2109 | } else { |
| 2112 | skb = skb_peek(&sk->sk_receive_queue); | 2110 | skb = skb_peek(&sk->sk_receive_queue); |
| 2113 | if (skb) | 2111 | if (skb) |
