aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r--net/unix/af_unix.c43
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
2193out_free: 2201out_free:
2194 skb_free_datagram(sk, skb); 2202 skb_free_datagram(sk, skb);
2195out_unlock:
2196 mutex_unlock(&u->readlock); 2203 mutex_unlock(&u->readlock);
2197out: 2204out:
2198 return err; 2205 return err;