patch-2.3.41 linux/net/socket.c

Next file: linux/net/sunrpc/xprt.c
Previous file: linux/net/rose/af_rose.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.40/linux/net/socket.c linux/net/socket.c
@@ -176,7 +176,10 @@
  *	Statistics counters of the socket lists
  */
 
-static int sockets_in_use  = 0;
+static union {
+	int	counter;
+	char	__pad[SMP_CACHE_BYTES];
+} sockets_in_use[NR_CPUS] __cacheline_aligned = {{0}};
 
 /*
  *	Support routines. Move socket addresses back and forth across the kernel/user
@@ -261,23 +264,14 @@
 			goto out;
 		}
 
-		lock_kernel();
 		file->f_dentry = d_alloc_root(sock->inode);
 		if (!file->f_dentry) {
-			unlock_kernel();
 			put_filp(file);
 			put_unused_fd(fd);
 			fd = -ENOMEM;
 			goto out;
 		}
 
-		/*
-		 * The socket maintains a reference to the inode, so we
-		 * have to increment the count.
-		 */
-		sock->inode->i_count++;
-		unlock_kernel();
-
 		file->f_op = &socket_file_ops;
 		file->f_mode = 3;
 		file->f_flags = O_RDWR;
@@ -360,7 +354,7 @@
 	sock->sk = NULL;
 	sock->file = NULL;
 
-	sockets_in_use++;
+	sockets_in_use[smp_processor_id()].counter++;
 	return sock;
 }
 
@@ -383,9 +377,12 @@
 	if (sock->fasync_list)
 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
 
-	--sockets_in_use;	/* Bookkeeping.. */
+	sockets_in_use[smp_processor_id()].counter--;
+	if (!sock->file) {
+		iput(sock->inode);
+		return;
+	}
 	sock->file=NULL;
-	iput(sock->inode);
 }
 
 int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size)
@@ -889,8 +886,6 @@
 	int err;
 	
 	if ((sock = sockfd_lookup(fd, &err)) != NULL) {
-		if ((unsigned) backlog == 0)	/* BSDism */
-			backlog = 1;
 		if ((unsigned) backlog > SOMAXCONN)
 			backlog = SOMAXCONN;
 		err=sock->ops->listen(sock, backlog);
@@ -943,6 +938,9 @@
 			goto out_release;
 	}
 
+	/* File flags are inherited via accept(). It looks silly, but we
+	 * have to be compatible with another OSes.
+	 */
 	if ((err = sock_map_fd(newsock)) < 0)
 		goto out_release;
 
@@ -1119,7 +1117,7 @@
 		flags |= MSG_DONTWAIT;
 	err=sock_recvmsg(sock, &msg, size, flags);
 
-	if(err >= 0 && addr != NULL)
+	if(err >= 0 && addr != NULL && msg.msg_namelen)
 	{
 		err2=move_addr_to_user(address, msg.msg_namelen, addr, addr_len);
 		if(err2<0)
@@ -1341,7 +1339,7 @@
 		goto out_freeiov;
 	len = err;
 
-	if (uaddr != NULL) {
+	if (uaddr != NULL && msg_sys.msg_namelen) {
 		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
 		if (err < 0)
 			goto out_freeiov;
@@ -1595,7 +1593,17 @@
 
 int socket_get_info(char *buffer, char **start, off_t offset, int length)
 {
-	int len = sprintf(buffer, "sockets: used %d\n", sockets_in_use);
+	int len, cpu;
+	int counter = 0;
+
+	for (cpu=0; cpu<smp_num_cpus; cpu++)
+		counter += sockets_in_use[cpu].counter;
+
+	/* It can be negative, by the way. 8) */
+	if (counter < 0)
+		counter = 0;
+
+	len = sprintf(buffer, "sockets: used %d\n", counter);
 	if (offset >= len)
 	{
 		*start = buffer;
@@ -1605,5 +1613,7 @@
 	len -= offset;
 	if (len > length)
 		len = length;
+	if (len < 0)
+		len = 0;
 	return len;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)