[NET]: use fget_light() in net/socket.c

Here's an updated copy of the patch to use fget_light in net/socket.c.
Rerunning the tests show a drop of ~80Mbit/s on average, which looks
bad until you see the drop in cpu usage from ~89% to ~82%.  That will
get fixed in another patch...

Before: max 8113.70, min 8026.32, avg 8072.34
 87380  16384  16384    10.01      8045.55   87.11    87.11    1.774   1.774
 87380  16384  16384    10.01      8065.14   90.86    90.86    1.846   1.846
 87380  16384  16384    10.00      8077.76   89.85    89.85    1.822   1.822
 87380  16384  16384    10.00      8026.32   89.80    89.80    1.833   1.833
 87380  16384  16384    10.01      8108.59   89.81    89.81    1.815   1.815
 87380  16384  16384    10.01      8034.53   89.01    89.01    1.815   1.815
 87380  16384  16384    10.00      8113.70   90.45    90.45    1.827   1.827
 87380  16384  16384    10.00      8111.37   89.90    89.90    1.816   1.816
 87380  16384  16384    10.01      8077.75   87.96    87.96    1.784   1.784
 87380  16384  16384    10.00      8062.70   90.25    90.25    1.834   1.834

After: max 8035.81, min 7963.69, avg 7998.14
 87380  16384  16384    10.01      8000.93   82.11    82.11    1.682   1.682
 87380  16384  16384    10.01      8016.17   83.67    83.67    1.710   1.710
 87380  16384  16384    10.01      7963.69   83.47    83.47    1.717   1.717
 87380  16384  16384    10.01      8014.35   81.71    81.71    1.671   1.671
 87380  16384  16384    10.00      7967.68   83.41    83.41    1.715   1.715
 87380  16384  16384    10.00      7995.22   81.00    81.00    1.660   1.660
 87380  16384  16384    10.00      8002.61   83.90    83.90    1.718   1.718
 87380  16384  16384    10.00      8035.81   81.71    81.71    1.666   1.666
 87380  16384  16384    10.01      8005.36   82.56    82.56    1.690   1.690
 87380  16384  16384    10.00      7979.61   82.50    82.50    1.694   1.694

Signed-off-by: Benjamin LaHaise <bcrl@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/socket.c b/net/socket.c
index 7428361..510ae18 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -426,6 +426,28 @@
 	return fd;
 }
 
+static struct socket *sock_from_file(struct file *file, int *err)
+{
+	struct inode *inode;
+	struct socket *sock;
+
+	if (file->f_op == &socket_file_ops)
+		return file->private_data;	/* set in sock_map_fd */
+
+	inode = file->f_dentry->d_inode;
+	if (!S_ISSOCK(inode->i_mode)) {
+		*err = -ENOTSOCK;
+		return NULL;
+	}
+
+	sock = SOCKET_I(inode);
+	if (sock->file != file) {
+		printk(KERN_ERR "socki_lookup: socket file changed!\n");
+		sock->file = file;
+	}
+	return sock;
+}
+
 /**
  *	sockfd_lookup	- 	Go from a file number to its socket slot
  *	@fd: file handle
@@ -442,33 +464,33 @@
 struct socket *sockfd_lookup(int fd, int *err)
 {
 	struct file *file;
-	struct inode *inode;
 	struct socket *sock;
 
-	if (!(file = fget(fd)))
-	{
+	if (!(file = fget(fd))) {
 		*err = -EBADF;
 		return NULL;
 	}
-
-	if (file->f_op == &socket_file_ops)
-		return file->private_data;	/* set in sock_map_fd */
-
-	inode = file->f_dentry->d_inode;
-	if (!S_ISSOCK(inode->i_mode)) {
-		*err = -ENOTSOCK;
+	sock = sock_from_file(file, err);
+	if (!sock)
 		fput(file);
-		return NULL;
-	}
-
-	sock = SOCKET_I(inode);
-	if (sock->file != file) {
-		printk(KERN_ERR "socki_lookup: socket file changed!\n");
-		sock->file = file;
-	}
 	return sock;
 }
 
+static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
+{
+	struct file *file;
+	struct socket *sock;
+
+	file = fget_light(fd, fput_needed);
+	if (file) {
+		sock = sock_from_file(file, err);
+		if (sock)
+			return sock;
+		fput_light(file, *fput_needed);
+	}
+	return NULL;
+}
+
 /**
  *	sock_alloc	-	allocate a socket
  *	
@@ -1301,19 +1323,17 @@
 {
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
-	int err;
+	int err, fput_needed;
 
-	if((sock = sockfd_lookup(fd,&err))!=NULL)
+	if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
 	{
 		if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
 			err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
-			if (err) {
-				sockfd_put(sock);
-				return err;
-			}
-			err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
+			if (!err)
+				err = sock->ops->bind(sock,
+					(struct sockaddr *)address, addrlen);
 		}
-		sockfd_put(sock);
+		fput_light(sock->file, fput_needed);
 	}			
 	return err;
 }
@@ -1330,20 +1350,17 @@
 asmlinkage long sys_listen(int fd, int backlog)
 {
 	struct socket *sock;
-	int err;
+	int err, fput_needed;
 	
-	if ((sock = sockfd_lookup(fd, &err)) != NULL) {
+	if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
 		if ((unsigned) backlog > sysctl_somaxconn)
 			backlog = sysctl_somaxconn;
 
 		err = security_socket_listen(sock, backlog);
-		if (err) {
-			sockfd_put(sock);
-			return err;
-		}
+		if (!err)
+			err = sock->ops->listen(sock, backlog);
 
-		err=sock->ops->listen(sock, backlog);
-		sockfd_put(sock);
+		fput_light(sock->file, fput_needed);
 	}
 	return err;
 }
@@ -1365,10 +1382,10 @@
 {
 	struct socket *sock, *newsock;
 	struct file *newfile;
-	int err, len, newfd;
+	int err, len, newfd, fput_needed;
 	char address[MAX_SOCK_ADDR];
 
-	sock = sockfd_lookup(fd, &err);
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
@@ -1421,7 +1438,7 @@
 	security_socket_post_accept(sock, newsock);
 
 out_put:
-	sockfd_put(sock);
+	fput_light(sock->file, fput_needed);
 out:
 	return err;
 out_fd:
@@ -1449,9 +1466,9 @@
 {
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
-	int err;
+	int err, fput_needed;
 
-	sock = sockfd_lookup(fd, &err);
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 	err = move_addr_to_kernel(uservaddr, addrlen, address);
@@ -1465,7 +1482,7 @@
 	err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
 				 sock->file->f_flags);
 out_put:
-	sockfd_put(sock);
+	fput_light(sock->file, fput_needed);
 out:
 	return err;
 }
@@ -1479,9 +1496,9 @@
 {
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
-	int len, err;
+	int len, err, fput_needed;
 	
-	sock = sockfd_lookup(fd, &err);
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
@@ -1495,7 +1512,7 @@
 	err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
 
 out_put:
-	sockfd_put(sock);
+	fput_light(sock->file, fput_needed);
 out:
 	return err;
 }
@@ -1509,20 +1526,19 @@
 {
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
-	int len, err;
+	int len, err, fput_needed;
 
-	if ((sock = sockfd_lookup(fd, &err))!=NULL)
-	{
+	if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
 		err = security_socket_getpeername(sock);
 		if (err) {
-			sockfd_put(sock);
+			fput_light(sock->file, fput_needed);
 			return err;
 		}
 
 		err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
 		if (!err)
 			err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
-		sockfd_put(sock);
+		fput_light(sock->file, fput_needed);
 	}
 	return err;
 }
@@ -1541,10 +1557,16 @@
 	int err;
 	struct msghdr msg;
 	struct iovec iov;
-	
-	sock = sockfd_lookup(fd, &err);
+	int fput_needed;
+	struct file *sock_file;
+
+	sock_file = fget_light(fd, &fput_needed);
+	if (!sock_file)
+		return -EBADF;
+
+	sock = sock_from_file(sock_file, &err);
 	if (!sock)
-		goto out;
+		goto out_put;
 	iov.iov_base=buff;
 	iov.iov_len=len;
 	msg.msg_name=NULL;
@@ -1553,8 +1575,7 @@
 	msg.msg_control=NULL;
 	msg.msg_controllen=0;
 	msg.msg_namelen=0;
-	if(addr)
-	{
+	if (addr) {
 		err = move_addr_to_kernel(addr, addr_len, address);
 		if (err < 0)
 			goto out_put;
@@ -1567,8 +1588,7 @@
 	err = sock_sendmsg(sock, &msg, len);
 
 out_put:		
-	sockfd_put(sock);
-out:
+	fput_light(sock_file, fput_needed);
 	return err;
 }
 
@@ -1595,8 +1615,14 @@
 	struct msghdr msg;
 	char address[MAX_SOCK_ADDR];
 	int err,err2;
+	struct file *sock_file;
+	int fput_needed;
 
-	sock = sockfd_lookup(fd, &err);
+	sock_file = fget_light(fd, &fput_needed);
+	if (!sock_file)
+		return -EBADF;
+
+	sock = sock_from_file(sock_file, &err);
 	if (!sock)
 		goto out;
 
@@ -1618,8 +1644,8 @@
 		if(err2<0)
 			err=err2;
 	}
-	sockfd_put(sock);			
 out:
+	fput_light(sock_file, fput_needed);
 	return err;
 }
 
@@ -1639,25 +1665,24 @@
 
 asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen)
 {
-	int err;
+	int err, fput_needed;
 	struct socket *sock;
 
 	if (optlen < 0)
 		return -EINVAL;
 			
-	if ((sock = sockfd_lookup(fd, &err))!=NULL)
+	if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL)
 	{
 		err = security_socket_setsockopt(sock,level,optname);
-		if (err) {
-			sockfd_put(sock);
-			return err;
-		}
+		if (err)
+			goto out_put;
 
 		if (level == SOL_SOCKET)
 			err=sock_setsockopt(sock,level,optname,optval,optlen);
 		else
 			err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
-		sockfd_put(sock);
+out_put:
+		fput_light(sock->file, fput_needed);
 	}
 	return err;
 }
@@ -1669,23 +1694,20 @@
 
 asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen)
 {
-	int err;
+	int err, fput_needed;
 	struct socket *sock;
 
-	if ((sock = sockfd_lookup(fd, &err))!=NULL)
-	{
-		err = security_socket_getsockopt(sock, level, 
-							   optname);
-		if (err) {
-			sockfd_put(sock);
-			return err;
-		}
+	if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
+		err = security_socket_getsockopt(sock, level, optname);
+		if (err)
+			goto out_put;
 
 		if (level == SOL_SOCKET)
 			err=sock_getsockopt(sock,level,optname,optval,optlen);
 		else
 			err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
-		sockfd_put(sock);
+out_put:
+		fput_light(sock->file, fput_needed);
 	}
 	return err;
 }
@@ -1697,19 +1719,15 @@
 
 asmlinkage long sys_shutdown(int fd, int how)
 {
-	int err;
+	int err, fput_needed;
 	struct socket *sock;
 
-	if ((sock = sockfd_lookup(fd, &err))!=NULL)
+	if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
 	{
 		err = security_socket_shutdown(sock, how);
-		if (err) {
-			sockfd_put(sock);
-			return err;
-		}
-				
-		err=sock->ops->shutdown(sock, how);
-		sockfd_put(sock);
+		if (!err)
+			err = sock->ops->shutdown(sock, how);
+		fput_light(sock->file, fput_needed);
 	}
 	return err;
 }
@@ -1738,6 +1756,7 @@
 	unsigned char *ctl_buf = ctl;
 	struct msghdr msg_sys;
 	int err, ctl_len, iov_size, total_len;
+	int fput_needed;
 	
 	err = -EFAULT;
 	if (MSG_CMSG_COMPAT & flags) {
@@ -1746,7 +1765,7 @@
 	} else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
 		return -EFAULT;
 
-	sock = sockfd_lookup(fd, &err);
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock) 
 		goto out;
 
@@ -1814,7 +1833,7 @@
 	if (iov != iovstack)
 		sock_kfree_s(sock->sk, iov, iov_size);
 out_put:
-	sockfd_put(sock);
+	fput_light(sock->file, fput_needed);
 out:       
 	return err;
 }
@@ -1832,6 +1851,7 @@
 	struct msghdr msg_sys;
 	unsigned long cmsg_ptr;
 	int err, iov_size, total_len, len;
+	int fput_needed;
 
 	/* kernel mode address */
 	char addr[MAX_SOCK_ADDR];
@@ -1847,7 +1867,7 @@
 		if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
 			return -EFAULT;
 
-	sock = sockfd_lookup(fd, &err);
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
@@ -1914,7 +1934,7 @@
 	if (iov != iovstack)
 		sock_kfree_s(sock->sk, iov, iov_size);
 out_put:
-	sockfd_put(sock);
+	fput_light(sock->file, fput_needed);
 out:
 	return err;
 }