diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 35 |
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 | ||
2165 | out_free: | 2171 | out_free: |
2166 | skb_free_datagram(sk, skb); | 2172 | skb_free_datagram(sk, skb); |
2167 | out_unlock: | ||
2168 | mutex_unlock(&u->readlock); | 2173 | mutex_unlock(&u->readlock); |
2169 | out: | 2174 | out: |
2170 | return err; | 2175 | return err; |