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.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 502e572af3fd..1c3c1f3a3ec4 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2078,8 +2078,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2078 struct scm_cookie scm; 2078 struct scm_cookie scm;
2079 struct sock *sk = sock->sk; 2079 struct sock *sk = sock->sk;
2080 struct unix_sock *u = unix_sk(sk); 2080 struct unix_sock *u = unix_sk(sk);
2081 int noblock = flags & MSG_DONTWAIT; 2081 struct sk_buff *skb, *last;
2082 struct sk_buff *skb; 2082 long timeo;
2083 int err; 2083 int err;
2084 int peeked, skip; 2084 int peeked, skip;
2085 2085
@@ -2087,26 +2087,32 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2087 if (flags&MSG_OOB) 2087 if (flags&MSG_OOB)
2088 goto out; 2088 goto out;
2089 2089
2090 err = mutex_lock_interruptible(&u->readlock); 2090 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
2091 if (unlikely(err)) {
2092 /* recvmsg() in non blocking mode is supposed to return -EAGAIN
2093 * sk_rcvtimeo is not honored by mutex_lock_interruptible()
2094 */
2095 err = noblock ? -EAGAIN : -ERESTARTSYS;
2096 goto out;
2097 }
2098 2091
2099 skip = sk_peek_offset(sk, flags); 2092 do {
2093 mutex_lock(&u->readlock);
2100 2094
2101 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err); 2095 skip = sk_peek_offset(sk, flags);
2102 if (!skb) { 2096 skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err,
2097 &last);
2098 if (skb)
2099 break;
2100
2101 mutex_unlock(&u->readlock);
2102
2103 if (err != -EAGAIN)
2104 break;
2105 } while (timeo &&
2106 !__skb_wait_for_more_packets(sk, &err, &timeo, last));
2107
2108 if (!skb) { /* implies readlock unlocked */
2103 unix_state_lock(sk); 2109 unix_state_lock(sk);
2104 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ 2110 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
2105 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && 2111 if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
2106 (sk->sk_shutdown & RCV_SHUTDOWN)) 2112 (sk->sk_shutdown & RCV_SHUTDOWN))
2107 err = 0; 2113 err = 0;
2108 unix_state_unlock(sk); 2114 unix_state_unlock(sk);
2109 goto out_unlock; 2115 goto out;
2110 } 2116 }
2111 2117
2112 if (wq_has_sleeper(&u->peer_wait)) 2118 if (wq_has_sleeper(&u->peer_wait))
@@ -2164,7 +2170,6 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2164 2170
2165out_free: 2171out_free:
2166 skb_free_datagram(sk, skb); 2172 skb_free_datagram(sk, skb);
2167out_unlock:
2168 mutex_unlock(&u->readlock); 2173 mutex_unlock(&u->readlock);
2169out: 2174out:
2170 return err; 2175 return err;