diff options
Diffstat (limited to 'net/unix/af_unix.c')
| -rw-r--r-- | net/unix/af_unix.c | 39 | 
1 files changed, 26 insertions, 13 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 4414a18c63b4..3c95304a0817 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -117,7 +117,7 @@  static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];  static DEFINE_SPINLOCK(unix_table_lock); -static atomic_t unix_nr_socks = ATOMIC_INIT(0); +static atomic_long_t unix_nr_socks;  #define unix_sockets_unbound	(&unix_socket_table[UNIX_HASH_SIZE]) @@ -360,13 +360,13 @@ static void unix_sock_destructor(struct sock *sk)  	if (u->addr)  		unix_release_addr(u->addr); -	atomic_dec(&unix_nr_socks); +	atomic_long_dec(&unix_nr_socks);  	local_bh_disable();  	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);  	local_bh_enable();  #ifdef UNIX_REFCNT_DEBUG -	printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk, -		atomic_read(&unix_nr_socks)); +	printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk, +		atomic_long_read(&unix_nr_socks));  #endif  } @@ -606,8 +606,8 @@ static struct sock *unix_create1(struct net *net, struct socket *sock)  	struct sock *sk = NULL;  	struct unix_sock *u; -	atomic_inc(&unix_nr_socks); -	if (atomic_read(&unix_nr_socks) > 2 * get_max_files()) +	atomic_long_inc(&unix_nr_socks); +	if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())  		goto out;  	sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto); @@ -632,7 +632,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock)  	unix_insert_socket(unix_sockets_unbound, sk);  out:  	if (sk == NULL) -		atomic_dec(&unix_nr_socks); +		atomic_long_dec(&unix_nr_socks);  	else {  		local_bh_disable();  		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); @@ -692,6 +692,7 @@ static int unix_autobind(struct socket *sock)  	static u32 ordernum = 1;  	struct unix_address *addr;  	int err; +	unsigned int retries = 0;  	mutex_lock(&u->readlock); @@ -717,9 +718,17 @@ retry:  	if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,  				      addr->hash)) {  		spin_unlock(&unix_table_lock); -		/* Sanity yield. It is unusual case, but yet... */ -		if (!(ordernum&0xFF)) -			yield(); +		/* +		 * __unix_find_socket_byname() may take long time if many names +		 * are already in use. +		 */ +		cond_resched(); +		/* Give up if all names seems to be in use. */ +		if (retries++ == 0xFFFFF) { +			err = -ENOSPC; +			kfree(addr); +			goto out; +		}  		goto retry;  	}  	addr->hash ^= sk->sk_type; @@ -1502,6 +1511,8 @@ restart:  		goto restart;  	} +	if (sock_flag(other, SOCK_RCVTSTAMP)) +		__net_timestamp(skb);  	skb_queue_tail(&other->sk_receive_queue, skb);  	unix_state_unlock(other);  	other->sk_data_ready(other, len); @@ -1713,6 +1724,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,  	if (err)  		goto out_free; +	if (sock_flag(sk, SOCK_RCVTSTAMP)) +		__sock_recv_timestamp(msg, sk, skb); +  	if (!siocb->scm) {  		siocb->scm = &tmp_scm;  		memset(&tmp_scm, 0, sizeof(tmp_scm)); @@ -2024,11 +2038,10 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table  	if (sk->sk_shutdown == SHUTDOWN_MASK)  		mask |= POLLHUP;  	if (sk->sk_shutdown & RCV_SHUTDOWN) -		mask |= POLLRDHUP; +		mask |= POLLRDHUP | POLLIN | POLLRDNORM;  	/* readable? */ -	if (!skb_queue_empty(&sk->sk_receive_queue) || -	    (sk->sk_shutdown & RCV_SHUTDOWN)) +	if (!skb_queue_empty(&sk->sk_receive_queue))  		mask |= POLLIN | POLLRDNORM;  	/* Connection-based need to check for termination and startup */  | 
