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 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 | ||
2177 | out_free: | 2185 | out_free: |
2178 | skb_free_datagram(sk, skb); | 2186 | skb_free_datagram(sk, skb); |
2179 | out_unlock: | ||
2180 | mutex_unlock(&u->readlock); | 2187 | mutex_unlock(&u->readlock); |
2181 | out: | 2188 | out: |
2182 | return err; | 2189 | return err; |