diff options
Diffstat (limited to 'net/unix/af_unix.c')
| -rw-r--r-- | net/unix/af_unix.c | 83 | 
1 files changed, 50 insertions, 33 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index bf338b782fc4..0f08c3177872 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -569,12 +569,6 @@ static void unix_sock_destructor(struct sock *sk)  	skb_queue_purge(&sk->sk_receive_queue); -#if IS_ENABLED(CONFIG_AF_UNIX_OOB) -	if (u->oob_skb) { -		kfree_skb(u->oob_skb); -		u->oob_skb = NULL; -	} -#endif  	DEBUG_NET_WARN_ON_ONCE(refcount_read(&sk->sk_wmem_alloc));  	DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk));  	DEBUG_NET_WARN_ON_ONCE(sk->sk_socket); @@ -620,6 +614,13 @@ static void unix_release_sock(struct sock *sk, int embrion)  	unix_state_unlock(sk); +#if IS_ENABLED(CONFIG_AF_UNIX_OOB) +	if (u->oob_skb) { +		kfree_skb(u->oob_skb); +		u->oob_skb = NULL; +	} +#endif +  	wake_up_interruptible_all(&u->peer_wait);  	if (skpair != NULL) { @@ -785,15 +786,45 @@ static int unix_set_peek_off(struct sock *sk, int val)  }  #ifdef CONFIG_PROC_FS +static int unix_count_nr_fds(struct sock *sk) +{ +	struct sk_buff *skb; +	struct unix_sock *u; +	int nr_fds = 0; + +	spin_lock(&sk->sk_receive_queue.lock); +	skb = skb_peek(&sk->sk_receive_queue); +	while (skb) { +		u = unix_sk(skb->sk); +		nr_fds += atomic_read(&u->scm_stat.nr_fds); +		skb = skb_peek_next(skb, &sk->sk_receive_queue); +	} +	spin_unlock(&sk->sk_receive_queue.lock); + +	return nr_fds; +} +  static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)  {  	struct sock *sk = sock->sk;  	struct unix_sock *u; +	int nr_fds;  	if (sk) { -		u = unix_sk(sock->sk); -		seq_printf(m, "scm_fds: %u\n", -			   atomic_read(&u->scm_stat.nr_fds)); +		u = unix_sk(sk); +		if (sock->type == SOCK_DGRAM) { +			nr_fds = atomic_read(&u->scm_stat.nr_fds); +			goto out_print; +		} + +		unix_state_lock(sk); +		if (sk->sk_state != TCP_LISTEN) +			nr_fds = atomic_read(&u->scm_stat.nr_fds); +		else +			nr_fds = unix_count_nr_fds(sk); +		unix_state_unlock(sk); +out_print: +		seq_printf(m, "scm_fds: %u\n", nr_fds);  	}  }  #else @@ -2506,32 +2537,18 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, size_t si  static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)  { -	int copied = 0; - -	while (1) { -		struct unix_sock *u = unix_sk(sk); -		struct sk_buff *skb; -		int used, err; - -		mutex_lock(&u->iolock); -		skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err); -		mutex_unlock(&u->iolock); -		if (!skb) -			return err; +	struct unix_sock *u = unix_sk(sk); +	struct sk_buff *skb; +	int err, copied; -		used = recv_actor(sk, skb); -		if (used <= 0) { -			if (!copied) -				copied = used; -			kfree_skb(skb); -			break; -		} else if (used <= skb->len) { -			copied += used; -		} +	mutex_lock(&u->iolock); +	skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err); +	mutex_unlock(&u->iolock); +	if (!skb) +		return err; -		kfree_skb(skb); -		break; -	} +	copied = recv_actor(sk, skb); +	kfree_skb(skb);  	return copied;  }  |