diff options
author | Hannes Frederic Sowa <hannes@stressinduktion.org> | 2015-05-21 11:00:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-25 00:06:59 -0400 |
commit | 2b514574f7e88c8498027ee366fd6e7aae5aa4b5 (patch) | |
tree | 1fd7303692dfbbf1c9c3348cb79961ceb5078cd1 /net/unix | |
parent | a60e3cc7c92973a31fad0fd04dc5cf4355d3d1ef (diff) |
net: af_unix: implement splice for stream af_unix sockets
unix_stream_recvmsg is refactored to unix_stream_read_generic in this
patch and enhanced to deal with pipe splicing. The refactoring is
inneglible, we mostly have to deal with a non-existing struct msghdr
argument.
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/unix')
-rw-r--r-- | net/unix/af_unix.c | 140 |
1 files changed, 119 insertions, 21 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 7762c0b46721..b8c44076c776 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -520,6 +520,9 @@ static int unix_stream_sendmsg(struct socket *, struct msghdr *, size_t); | |||
520 | static int unix_stream_recvmsg(struct socket *, struct msghdr *, size_t, int); | 520 | static int unix_stream_recvmsg(struct socket *, struct msghdr *, size_t, int); |
521 | static ssize_t unix_stream_sendpage(struct socket *, struct page *, int offset, | 521 | static ssize_t unix_stream_sendpage(struct socket *, struct page *, int offset, |
522 | size_t size, int flags); | 522 | size_t size, int flags); |
523 | static ssize_t unix_stream_splice_read(struct socket *, loff_t *ppos, | ||
524 | struct pipe_inode_info *, size_t size, | ||
525 | unsigned int flags); | ||
523 | static int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t); | 526 | static int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t); |
524 | static int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int); | 527 | static int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int); |
525 | static int unix_dgram_connect(struct socket *, struct sockaddr *, | 528 | static int unix_dgram_connect(struct socket *, struct sockaddr *, |
@@ -561,6 +564,7 @@ static const struct proto_ops unix_stream_ops = { | |||
561 | .recvmsg = unix_stream_recvmsg, | 564 | .recvmsg = unix_stream_recvmsg, |
562 | .mmap = sock_no_mmap, | 565 | .mmap = sock_no_mmap, |
563 | .sendpage = unix_stream_sendpage, | 566 | .sendpage = unix_stream_sendpage, |
567 | .splice_read = unix_stream_splice_read, | ||
564 | .set_peek_off = unix_set_peek_off, | 568 | .set_peek_off = unix_set_peek_off, |
565 | }; | 569 | }; |
566 | 570 | ||
@@ -1957,8 +1961,9 @@ out: | |||
1957 | * Sleep until more data has arrived. But check for races.. | 1961 | * Sleep until more data has arrived. But check for races.. |
1958 | */ | 1962 | */ |
1959 | static long unix_stream_data_wait(struct sock *sk, long timeo, | 1963 | static long unix_stream_data_wait(struct sock *sk, long timeo, |
1960 | struct sk_buff *last) | 1964 | struct sk_buff *last, unsigned int last_len) |
1961 | { | 1965 | { |
1966 | struct sk_buff *tail; | ||
1962 | DEFINE_WAIT(wait); | 1967 | DEFINE_WAIT(wait); |
1963 | 1968 | ||
1964 | unix_state_lock(sk); | 1969 | unix_state_lock(sk); |
@@ -1966,7 +1971,9 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, | |||
1966 | for (;;) { | 1971 | for (;;) { |
1967 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 1972 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1968 | 1973 | ||
1969 | if (skb_peek_tail(&sk->sk_receive_queue) != last || | 1974 | tail = skb_peek_tail(&sk->sk_receive_queue); |
1975 | if (tail != last || | ||
1976 | (tail && tail->len != last_len) || | ||
1970 | sk->sk_err || | 1977 | sk->sk_err || |
1971 | (sk->sk_shutdown & RCV_SHUTDOWN) || | 1978 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
1972 | signal_pending(current) || | 1979 | signal_pending(current) || |
@@ -1990,38 +1997,50 @@ static unsigned int unix_skb_len(const struct sk_buff *skb) | |||
1990 | return skb->len - UNIXCB(skb).consumed; | 1997 | return skb->len - UNIXCB(skb).consumed; |
1991 | } | 1998 | } |
1992 | 1999 | ||
1993 | static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, | 2000 | struct unix_stream_read_state { |
1994 | size_t size, int flags) | 2001 | int (*recv_actor)(struct sk_buff *, int, int, |
2002 | struct unix_stream_read_state *); | ||
2003 | struct socket *socket; | ||
2004 | struct msghdr *msg; | ||
2005 | struct pipe_inode_info *pipe; | ||
2006 | size_t size; | ||
2007 | int flags; | ||
2008 | unsigned int splice_flags; | ||
2009 | }; | ||
2010 | |||
2011 | static int unix_stream_read_generic(struct unix_stream_read_state *state) | ||
1995 | { | 2012 | { |
1996 | struct scm_cookie scm; | 2013 | struct scm_cookie scm; |
2014 | struct socket *sock = state->socket; | ||
1997 | struct sock *sk = sock->sk; | 2015 | struct sock *sk = sock->sk; |
1998 | struct unix_sock *u = unix_sk(sk); | 2016 | struct unix_sock *u = unix_sk(sk); |
1999 | DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name); | ||
2000 | int copied = 0; | 2017 | int copied = 0; |
2018 | int flags = state->flags; | ||
2001 | int noblock = flags & MSG_DONTWAIT; | 2019 | int noblock = flags & MSG_DONTWAIT; |
2002 | int check_creds = 0; | 2020 | bool check_creds = false; |
2003 | int target; | 2021 | int target; |
2004 | int err = 0; | 2022 | int err = 0; |
2005 | long timeo; | 2023 | long timeo; |
2006 | int skip; | 2024 | int skip; |
2025 | size_t size = state->size; | ||
2026 | unsigned int last_len; | ||
2007 | 2027 | ||
2008 | err = -EINVAL; | 2028 | err = -EINVAL; |
2009 | if (sk->sk_state != TCP_ESTABLISHED) | 2029 | if (sk->sk_state != TCP_ESTABLISHED) |
2010 | goto out; | 2030 | goto out; |
2011 | 2031 | ||
2012 | err = -EOPNOTSUPP; | 2032 | err = -EOPNOTSUPP; |
2013 | if (flags&MSG_OOB) | 2033 | if (flags & MSG_OOB) |
2014 | goto out; | 2034 | goto out; |
2015 | 2035 | ||
2016 | target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); | 2036 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); |
2017 | timeo = sock_rcvtimeo(sk, noblock); | 2037 | timeo = sock_rcvtimeo(sk, noblock); |
2018 | 2038 | ||
2039 | memset(&scm, 0, sizeof(scm)); | ||
2040 | |||
2019 | /* Lock the socket to prevent queue disordering | 2041 | /* Lock the socket to prevent queue disordering |
2020 | * while sleeps in memcpy_tomsg | 2042 | * while sleeps in memcpy_tomsg |
2021 | */ | 2043 | */ |
2022 | |||
2023 | memset(&scm, 0, sizeof(scm)); | ||
2024 | |||
2025 | err = mutex_lock_interruptible(&u->readlock); | 2044 | err = mutex_lock_interruptible(&u->readlock); |
2026 | if (unlikely(err)) { | 2045 | if (unlikely(err)) { |
2027 | /* recvmsg() in non blocking mode is supposed to return -EAGAIN | 2046 | /* recvmsg() in non blocking mode is supposed to return -EAGAIN |
@@ -2037,6 +2056,7 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, | |||
2037 | 2056 | ||
2038 | unix_state_lock(sk); | 2057 | unix_state_lock(sk); |
2039 | last = skb = skb_peek(&sk->sk_receive_queue); | 2058 | last = skb = skb_peek(&sk->sk_receive_queue); |
2059 | last_len = last ? last->len : 0; | ||
2040 | again: | 2060 | again: |
2041 | if (skb == NULL) { | 2061 | if (skb == NULL) { |
2042 | unix_sk(sk)->recursion_level = 0; | 2062 | unix_sk(sk)->recursion_level = 0; |
@@ -2059,16 +2079,17 @@ again: | |||
2059 | break; | 2079 | break; |
2060 | mutex_unlock(&u->readlock); | 2080 | mutex_unlock(&u->readlock); |
2061 | 2081 | ||
2062 | timeo = unix_stream_data_wait(sk, timeo, last); | 2082 | timeo = unix_stream_data_wait(sk, timeo, last, |
2083 | last_len); | ||
2063 | 2084 | ||
2064 | if (signal_pending(current) | 2085 | if (signal_pending(current) || |
2065 | || mutex_lock_interruptible(&u->readlock)) { | 2086 | mutex_lock_interruptible(&u->readlock)) { |
2066 | err = sock_intr_errno(timeo); | 2087 | err = sock_intr_errno(timeo); |
2067 | goto out; | 2088 | goto out; |
2068 | } | 2089 | } |
2069 | 2090 | ||
2070 | continue; | 2091 | continue; |
2071 | unlock: | 2092 | unlock: |
2072 | unix_state_unlock(sk); | 2093 | unix_state_unlock(sk); |
2073 | break; | 2094 | break; |
2074 | } | 2095 | } |
@@ -2077,6 +2098,7 @@ again: | |||
2077 | while (skip >= unix_skb_len(skb)) { | 2098 | while (skip >= unix_skb_len(skb)) { |
2078 | skip -= unix_skb_len(skb); | 2099 | skip -= unix_skb_len(skb); |
2079 | last = skb; | 2100 | last = skb; |
2101 | last_len = skb->len; | ||
2080 | skb = skb_peek_next(skb, &sk->sk_receive_queue); | 2102 | skb = skb_peek_next(skb, &sk->sk_receive_queue); |
2081 | if (!skb) | 2103 | if (!skb) |
2082 | goto again; | 2104 | goto again; |
@@ -2093,18 +2115,20 @@ again: | |||
2093 | } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { | 2115 | } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { |
2094 | /* Copy credentials */ | 2116 | /* Copy credentials */ |
2095 | scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); | 2117 | scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); |
2096 | check_creds = 1; | 2118 | check_creds = true; |
2097 | } | 2119 | } |
2098 | 2120 | ||
2099 | /* Copy address just once */ | 2121 | /* Copy address just once */ |
2100 | if (sunaddr) { | 2122 | if (state->msg && state->msg->msg_name) { |
2101 | unix_copy_addr(msg, skb->sk); | 2123 | DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, |
2124 | state->msg->msg_name); | ||
2125 | unix_copy_addr(state->msg, skb->sk); | ||
2102 | sunaddr = NULL; | 2126 | sunaddr = NULL; |
2103 | } | 2127 | } |
2104 | 2128 | ||
2105 | chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size); | 2129 | chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size); |
2106 | if (skb_copy_datagram_msg(skb, UNIXCB(skb).consumed + skip, | 2130 | chunk = state->recv_actor(skb, skip, chunk, state); |
2107 | msg, chunk)) { | 2131 | if (chunk < 0) { |
2108 | if (copied == 0) | 2132 | if (copied == 0) |
2109 | copied = -EFAULT; | 2133 | copied = -EFAULT; |
2110 | break; | 2134 | break; |
@@ -2142,11 +2166,85 @@ again: | |||
2142 | } while (size); | 2166 | } while (size); |
2143 | 2167 | ||
2144 | mutex_unlock(&u->readlock); | 2168 | mutex_unlock(&u->readlock); |
2145 | scm_recv(sock, msg, &scm, flags); | 2169 | if (state->msg) |
2170 | scm_recv(sock, state->msg, &scm, flags); | ||
2171 | else | ||
2172 | scm_destroy(&scm); | ||
2146 | out: | 2173 | out: |
2147 | return copied ? : err; | 2174 | return copied ? : err; |
2148 | } | 2175 | } |
2149 | 2176 | ||
2177 | static int unix_stream_read_actor(struct sk_buff *skb, | ||
2178 | int skip, int chunk, | ||
2179 | struct unix_stream_read_state *state) | ||
2180 | { | ||
2181 | int ret; | ||
2182 | |||
2183 | ret = skb_copy_datagram_msg(skb, UNIXCB(skb).consumed + skip, | ||
2184 | state->msg, chunk); | ||
2185 | return ret ?: chunk; | ||
2186 | } | ||
2187 | |||
2188 | static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, | ||
2189 | size_t size, int flags) | ||
2190 | { | ||
2191 | struct unix_stream_read_state state = { | ||
2192 | .recv_actor = unix_stream_read_actor, | ||
2193 | .socket = sock, | ||
2194 | .msg = msg, | ||
2195 | .size = size, | ||
2196 | .flags = flags | ||
2197 | }; | ||
2198 | |||
2199 | return unix_stream_read_generic(&state); | ||
2200 | } | ||
2201 | |||
2202 | static ssize_t skb_unix_socket_splice(struct sock *sk, | ||
2203 | struct pipe_inode_info *pipe, | ||
2204 | struct splice_pipe_desc *spd) | ||
2205 | { | ||
2206 | int ret; | ||
2207 | struct unix_sock *u = unix_sk(sk); | ||
2208 | |||
2209 | mutex_unlock(&u->readlock); | ||
2210 | ret = splice_to_pipe(pipe, spd); | ||
2211 | mutex_lock(&u->readlock); | ||
2212 | |||
2213 | return ret; | ||
2214 | } | ||
2215 | |||
2216 | static int unix_stream_splice_actor(struct sk_buff *skb, | ||
2217 | int skip, int chunk, | ||
2218 | struct unix_stream_read_state *state) | ||
2219 | { | ||
2220 | return skb_splice_bits(skb, state->socket->sk, | ||
2221 | UNIXCB(skb).consumed + skip, | ||
2222 | state->pipe, chunk, state->splice_flags, | ||
2223 | skb_unix_socket_splice); | ||
2224 | } | ||
2225 | |||
2226 | static ssize_t unix_stream_splice_read(struct socket *sock, loff_t *ppos, | ||
2227 | struct pipe_inode_info *pipe, | ||
2228 | size_t size, unsigned int flags) | ||
2229 | { | ||
2230 | struct unix_stream_read_state state = { | ||
2231 | .recv_actor = unix_stream_splice_actor, | ||
2232 | .socket = sock, | ||
2233 | .pipe = pipe, | ||
2234 | .size = size, | ||
2235 | .splice_flags = flags, | ||
2236 | }; | ||
2237 | |||
2238 | if (unlikely(*ppos)) | ||
2239 | return -ESPIPE; | ||
2240 | |||
2241 | if (sock->file->f_flags & O_NONBLOCK || | ||
2242 | flags & SPLICE_F_NONBLOCK) | ||
2243 | state.flags = MSG_DONTWAIT; | ||
2244 | |||
2245 | return unix_stream_read_generic(&state); | ||
2246 | } | ||
2247 | |||
2150 | static int unix_shutdown(struct socket *sock, int mode) | 2248 | static int unix_shutdown(struct socket *sock, int mode) |
2151 | { | 2249 | { |
2152 | struct sock *sk = sock->sk; | 2250 | struct sock *sk = sock->sk; |