diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e3f85bc8b135..c5bf5ef2bf89 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -451,7 +451,7 @@ static void unix_write_space(struct sock *sk) | |||
451 | rcu_read_lock(); | 451 | rcu_read_lock(); |
452 | if (unix_writable(sk)) { | 452 | if (unix_writable(sk)) { |
453 | wq = rcu_dereference(sk->sk_wq); | 453 | wq = rcu_dereference(sk->sk_wq); |
454 | if (wq_has_sleeper(wq)) | 454 | if (skwq_has_sleeper(wq)) |
455 | wake_up_interruptible_sync_poll(&wq->wait, | 455 | wake_up_interruptible_sync_poll(&wq->wait, |
456 | POLLOUT | POLLWRNORM | POLLWRBAND); | 456 | POLLOUT | POLLWRNORM | POLLWRBAND); |
457 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 457 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
@@ -2108,8 +2108,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
2108 | struct scm_cookie scm; | 2108 | struct scm_cookie scm; |
2109 | struct sock *sk = sock->sk; | 2109 | struct sock *sk = sock->sk; |
2110 | struct unix_sock *u = unix_sk(sk); | 2110 | struct unix_sock *u = unix_sk(sk); |
2111 | int noblock = flags & MSG_DONTWAIT; | 2111 | struct sk_buff *skb, *last; |
2112 | struct sk_buff *skb; | 2112 | long timeo; |
2113 | int err; | 2113 | int err; |
2114 | int peeked, skip; | 2114 | int peeked, skip; |
2115 | 2115 | ||
@@ -2117,30 +2117,38 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
2117 | if (flags&MSG_OOB) | 2117 | if (flags&MSG_OOB) |
2118 | goto out; | 2118 | goto out; |
2119 | 2119 | ||
2120 | err = mutex_lock_interruptible(&u->readlock); | 2120 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
2121 | if (unlikely(err)) { | ||
2122 | /* recvmsg() in non blocking mode is supposed to return -EAGAIN | ||
2123 | * sk_rcvtimeo is not honored by mutex_lock_interruptible() | ||
2124 | */ | ||
2125 | err = noblock ? -EAGAIN : -ERESTARTSYS; | ||
2126 | goto out; | ||
2127 | } | ||
2128 | 2121 | ||
2129 | skip = sk_peek_offset(sk, flags); | 2122 | do { |
2123 | mutex_lock(&u->readlock); | ||
2130 | 2124 | ||
2131 | skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err); | 2125 | skip = sk_peek_offset(sk, flags); |
2132 | if (!skb) { | 2126 | skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err, |
2127 | &last); | ||
2128 | if (skb) | ||
2129 | break; | ||
2130 | |||
2131 | mutex_unlock(&u->readlock); | ||
2132 | |||
2133 | if (err != -EAGAIN) | ||
2134 | break; | ||
2135 | } while (timeo && | ||
2136 | !__skb_wait_for_more_packets(sk, &err, &timeo, last)); | ||
2137 | |||
2138 | if (!skb) { /* implies readlock unlocked */ | ||
2133 | unix_state_lock(sk); | 2139 | unix_state_lock(sk); |
2134 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ | 2140 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ |
2135 | if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && | 2141 | if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && |
2136 | (sk->sk_shutdown & RCV_SHUTDOWN)) | 2142 | (sk->sk_shutdown & RCV_SHUTDOWN)) |
2137 | err = 0; | 2143 | err = 0; |
2138 | unix_state_unlock(sk); | 2144 | unix_state_unlock(sk); |
2139 | goto out_unlock; | 2145 | goto out; |
2140 | } | 2146 | } |
2141 | 2147 | ||
2142 | wake_up_interruptible_sync_poll(&u->peer_wait, | 2148 | if (wq_has_sleeper(&u->peer_wait)) |
2143 | POLLOUT | POLLWRNORM | POLLWRBAND); | 2149 | wake_up_interruptible_sync_poll(&u->peer_wait, |
2150 | POLLOUT | POLLWRNORM | | ||
2151 | POLLWRBAND); | ||
2144 | 2152 | ||
2145 | if (msg->msg_name) | 2153 | if (msg->msg_name) |
2146 | unix_copy_addr(msg, skb->sk); | 2154 | unix_copy_addr(msg, skb->sk); |
@@ -2192,7 +2200,6 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
2192 | 2200 | ||
2193 | out_free: | 2201 | out_free: |
2194 | skb_free_datagram(sk, skb); | 2202 | skb_free_datagram(sk, skb); |
2195 | out_unlock: | ||
2196 | mutex_unlock(&u->readlock); | 2203 | mutex_unlock(&u->readlock); |
2197 | out: | 2204 | out: |
2198 | return err; | 2205 | return err; |