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 ef05cd9403d4..e6d35569f757 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);
@@ -2092,8 +2092,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2092 struct scm_cookie scm; 2092 struct scm_cookie scm;
2093 struct sock *sk = sock->sk; 2093 struct sock *sk = sock->sk;
2094 struct unix_sock *u = unix_sk(sk); 2094 struct unix_sock *u = unix_sk(sk);
2095 int noblock = flags & MSG_DONTWAIT; 2095 struct sk_buff *skb, *last;
2096 struct sk_buff *skb; 2096 long timeo;
2097 int err; 2097 int err;
2098 int peeked, skip; 2098 int peeked, skip;
2099 2099
@@ -2101,30 +2101,38 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2101 if (flags&MSG_OOB) 2101 if (flags&MSG_OOB)
2102 goto out; 2102 goto out;
2103 2103
2104 err = mutex_lock_interruptible(&u->readlock); 2104 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
2105 if (unlikely(err)) {
2106 /* recvmsg() in non blocking mode is supposed to return -EAGAIN
2107 * sk_rcvtimeo is not honored by mutex_lock_interruptible()
2108 */
2109 err = noblock ? -EAGAIN : -ERESTARTSYS;
2110 goto out;
2111 }
2112 2105
2113 skip = sk_peek_offset(sk, flags); 2106 do {
2107 mutex_lock(&u->readlock);
2114 2108
2115 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err); 2109 skip = sk_peek_offset(sk, flags);
2116 if (!skb) { 2110 skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err,
2111 &last);
2112 if (skb)
2113 break;
2114
2115 mutex_unlock(&u->readlock);
2116
2117 if (err != -EAGAIN)
2118 break;
2119 } while (timeo &&
2120 !__skb_wait_for_more_packets(sk, &err, &timeo, last));
2121
2122 if (!skb) { /* implies readlock unlocked */
2117 unix_state_lock(sk); 2123 unix_state_lock(sk);
2118 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ 2124 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
2119 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && 2125 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
2120 (sk->sk_shutdown & RCV_SHUTDOWN)) 2126 (sk->sk_shutdown & RCV_SHUTDOWN))
2121 err = 0; 2127 err = 0;
2122 unix_state_unlock(sk); 2128 unix_state_unlock(sk);
2123 goto out_unlock; 2129 goto out;
2124 } 2130 }
2125 2131
2126 wake_up_interruptible_sync_poll(&u->peer_wait, 2132 if (wq_has_sleeper(&u->peer_wait))
2127 POLLOUT | POLLWRNORM | POLLWRBAND); 2133 wake_up_interruptible_sync_poll(&u->peer_wait,
2134 POLLOUT | POLLWRNORM |
2135 POLLWRBAND);
2128 2136
2129 if (msg->msg_name) 2137 if (msg->msg_name)
2130 unix_copy_addr(msg, skb->sk); 2138 unix_copy_addr(msg, skb->sk);
@@ -2176,7 +2184,6 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2176 2184
2177out_free: 2185out_free:
2178 skb_free_datagram(sk, skb); 2186 skb_free_datagram(sk, skb);
2179out_unlock:
2180 mutex_unlock(&u->readlock); 2187 mutex_unlock(&u->readlock);
2181out: 2188out:
2182 return err; 2189 return err;