diff options
Diffstat (limited to 'net/unix/af_unix.c')
| -rw-r--r-- | net/unix/af_unix.c | 29 | 
1 files changed, 15 insertions, 14 deletions
| diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index fb31e8a4409e..e7728b57a8c7 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -603,7 +603,7 @@ static void unix_release_sock(struct sock *sk, int embrion)  	/* Clear state */  	unix_state_lock(sk);  	sock_orphan(sk); -	sk->sk_shutdown = SHUTDOWN_MASK; +	WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);  	path	     = u->path;  	u->path.dentry = NULL;  	u->path.mnt = NULL; @@ -628,7 +628,7 @@ static void unix_release_sock(struct sock *sk, int embrion)  		if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {  			unix_state_lock(skpair);  			/* No more writes */ -			skpair->sk_shutdown = SHUTDOWN_MASK; +			WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK);  			if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)  				WRITE_ONCE(skpair->sk_err, ECONNRESET);  			unix_state_unlock(skpair); @@ -1442,7 +1442,7 @@ static long unix_wait_for_peer(struct sock *other, long timeo)  	sched = !sock_flag(other, SOCK_DEAD) &&  		!(other->sk_shutdown & RCV_SHUTDOWN) && -		unix_recvq_full(other); +		unix_recvq_full_lockless(other);  	unix_state_unlock(other); @@ -2553,7 +2553,7 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)  {  	struct unix_sock *u = unix_sk(sk);  	struct sk_buff *skb; -	int err, copied; +	int err;  	mutex_lock(&u->iolock);  	skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err); @@ -2561,10 +2561,7 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)  	if (!skb)  		return err; -	copied = recv_actor(sk, skb); -	kfree_skb(skb); - -	return copied; +	return recv_actor(sk, skb);  }  /* @@ -3008,7 +3005,7 @@ static int unix_shutdown(struct socket *sock, int mode)  	++mode;  	unix_state_lock(sk); -	sk->sk_shutdown |= mode; +	WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | mode);  	other = unix_peer(sk);  	if (other)  		sock_hold(other); @@ -3028,7 +3025,7 @@ static int unix_shutdown(struct socket *sock, int mode)  		if (mode&SEND_SHUTDOWN)  			peer_mode |= RCV_SHUTDOWN;  		unix_state_lock(other); -		other->sk_shutdown |= peer_mode; +		WRITE_ONCE(other->sk_shutdown, other->sk_shutdown | peer_mode);  		unix_state_unlock(other);  		other->sk_state_change(other);  		if (peer_mode == SHUTDOWN_MASK) @@ -3160,16 +3157,18 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa  {  	struct sock *sk = sock->sk;  	__poll_t mask; +	u8 shutdown;  	sock_poll_wait(file, sock, wait);  	mask = 0; +	shutdown = READ_ONCE(sk->sk_shutdown);  	/* exceptional events? */  	if (READ_ONCE(sk->sk_err))  		mask |= EPOLLERR; -	if (sk->sk_shutdown == SHUTDOWN_MASK) +	if (shutdown == SHUTDOWN_MASK)  		mask |= EPOLLHUP; -	if (sk->sk_shutdown & RCV_SHUTDOWN) +	if (shutdown & RCV_SHUTDOWN)  		mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;  	/* readable? */ @@ -3203,9 +3202,11 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,  	struct sock *sk = sock->sk, *other;  	unsigned int writable;  	__poll_t mask; +	u8 shutdown;  	sock_poll_wait(file, sock, wait);  	mask = 0; +	shutdown = READ_ONCE(sk->sk_shutdown);  	/* exceptional events? */  	if (READ_ONCE(sk->sk_err) || @@ -3213,9 +3214,9 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,  		mask |= EPOLLERR |  			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0); -	if (sk->sk_shutdown & RCV_SHUTDOWN) +	if (shutdown & RCV_SHUTDOWN)  		mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM; -	if (sk->sk_shutdown == SHUTDOWN_MASK) +	if (shutdown == SHUTDOWN_MASK)  		mask |= EPOLLHUP;  	/* readable? */ | 
