Index: uipc_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.203
diff -u -r1.203 uipc_syscalls.c
--- uipc_syscalls.c	24 Oct 2004 20:09:59 -0000	1.203
+++ uipc_syscalls.c	24 Oct 2004 23:29:52 -0000
@@ -101,6 +101,40 @@
     "Number of sendfile(2) sf_bufs in use");
 
 /*
+ * Convert a user file descriptor to a kernel file entry.  A reference on the
+ * file entry is held upon returning.  This is lighter weight than
+ * fgetsock(), which bumps the socket reference drops the file reference
+ * count instead, as this approach avoids several additional mutex operations
+ * associated with the additional reference count.
+ */
+static int
+getsock(struct filedesc *fdp, int fd, struct file **fpp)
+{
+	struct file *fp;
+	int error;
+
+	fp = NULL;
+	if (fdp == NULL)
+		error = EBADF;
+	else {
+		FILEDESC_LOCK(fdp);
+		if ((u_int)fd >= fdp->fd_nfiles ||
+		    (fp = fdp->fd_ofiles[fd]) == NULL)
+			error = EBADF;
+		else if (fp->f_type != DTYPE_SOCKET) {
+			fp = NULL;
+			error = ENOTSOCK;
+		} else {
+			fhold(fp);
+			error = 0;
+		}
+		FILEDESC_UNLOCK(fdp);
+	}
+	*fpp = fp;
+	return (error);
+}
+
+/*
  * System call interface to the socket abstraction.
  */
 #if defined(COMPAT_43)
@@ -184,11 +218,14 @@
 	struct sockaddr *sa;
 {
 	struct socket *so;
+	struct file *fp;
 	int error;
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, fd, &so, NULL)) != 0)
+	error = getsock(td->td_proc->p_fd, fd, &fp);
+	if (error)
 		goto done2;
+	so = fp->f_data;
 #ifdef MAC
 	SOCK_LOCK(so);
 	error = mac_check_socket_bind(td->td_ucred, so, sa);
@@ -200,7 +237,7 @@
 #ifdef MAC
 done1:
 #endif
-	fputsock(so);
+	fdrop(fp, td);
 done2:
 	NET_UNLOCK_GIANT();
 	FREE(sa, M_SONAME);
@@ -220,10 +257,13 @@
 	} */ *uap;
 {
 	struct socket *so;
+	struct file *fp;
 	int error;
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, uap->s, &so, NULL)) == 0) {
+	error = getsock(td->td_proc->p_fd, uap->s, &fp);
+	if (error == 0) {
+		so = fp->f_data;
 #ifdef MAC
 		SOCK_LOCK(so);
 		error = mac_check_socket_listen(td->td_ucred, so);
@@ -235,7 +275,7 @@
 #ifdef MAC
 done:
 #endif
-		fputsock(so);
+		fdrop(fp, td);
 	}
 	NET_UNLOCK_GIANT();
 	return(error);
@@ -476,12 +516,15 @@
 	struct sockaddr *sa;
 {
 	struct socket *so;
+	struct file *fp;
 	int error, s;
 	int interrupted = 0;
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, fd, &so, NULL)) != 0)
+	error = getsock(td->td_proc->p_fd, fd, &fp);
+	if (error)
 		goto done2;
+	so = fp->f_data;
 	if (so->so_state & SS_ISCONNECTING) {
 		error = EALREADY;
 		goto done1;
@@ -523,7 +566,7 @@
 	if (error == ERESTART)
 		error = EINTR;
 done1:
-	fputsock(so);
+	fdrop(fp, td);
 done2:
 	NET_UNLOCK_GIANT();
 	FREE(sa, M_SONAME);
@@ -695,6 +738,7 @@
 	int flags;
 	struct mbuf *control;
 {
+	struct file *fp;
 	struct uio auio;
 	struct iovec *iov;
 	struct socket *so;
@@ -705,8 +749,10 @@
 #endif
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, s, &so, NULL)) != 0)
+	error = getsock(td->td_proc->p_fd, s, &fp);
+	if (error)
 		goto bad2;
+	so = (struct socket *)fp->f_data;
 
 #ifdef MAC
 	SOCK_LOCK(so);
@@ -757,7 +803,7 @@
 	}
 #endif
 bad:
-	fputsock(so);
+	fdrop(fp, td);
 bad2:
 	NET_UNLOCK_GIANT();
 	return (error);
@@ -901,6 +947,7 @@
 	int error;
 	struct mbuf *m, *control = 0;
 	caddr_t ctlbuf;
+	struct file *fp;
 	struct socket *so;
 	struct sockaddr *fromsa = 0;
 #ifdef KTRACE
@@ -908,17 +955,19 @@
 #endif
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, s, &so, NULL)) != 0) {
+	error = getsock(td->td_proc->p_fd, s, &fp);
+	if (error) {
 		NET_UNLOCK_GIANT();
 		return (error);
 	}
+	so = fp->f_data;
 
 #ifdef MAC
 	SOCK_LOCK(so);
 	error = mac_check_socket_receive(td->td_ucred, so);
 	SOCK_UNLOCK(so);
 	if (error) {
-		fputsock(so);
+		fdrop(fp, td);
 		NET_UNLOCK_GIANT();
 		return (error);
 	}
@@ -934,7 +983,7 @@
 	iov = mp->msg_iov;
 	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
 		if ((auio.uio_resid += iov->iov_len) < 0) {
-			fputsock(so);
+			fdrop(fp, td);
 			NET_UNLOCK_GIANT();
 			return (EINVAL);
 		}
@@ -1035,7 +1084,7 @@
 		mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
 	}
 out:
-	fputsock(so);
+	fdrop(fp, td);
 	NET_UNLOCK_GIANT();
 	if (fromsa)
 		FREE(fromsa, M_SONAME);
@@ -1216,15 +1265,18 @@
 	} */ *uap;
 {
 	struct socket *so;
+	struct file *fp;
 	int error;
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, uap->s, &so, NULL)) == 0) {
+	error = getsock(td->td_proc->p_fd, uap->s, &fp);
+	if (error == 0) {
+		so = fp->f_data;
 		error = soshutdown(so, uap->how);
-		fputsock(so);
+		fdrop(fp, td);
 	}
 	NET_UNLOCK_GIANT();
-	return(error);
+	return (error);
 }
 
 /*
@@ -1259,6 +1311,7 @@
 {
 	int error;
 	struct socket *so;
+	struct file *fp;
 	struct sockopt sopt;
 
 	if (val == NULL && valsize != 0)
@@ -1283,9 +1336,11 @@
 	}
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, s, &so, NULL)) == 0) {
+	error = getsock(td->td_proc->p_fd, s, &fp);
+	if (error == 0) {
+		so = fp->f_data;
 		error = sosetopt(so, &sopt);
-		fputsock(so);
+		fdrop(fp, td);
 	}
 	NET_UNLOCK_GIANT();
 	return(error);
@@ -1339,6 +1394,7 @@
 {
 	int error;
 	struct  socket *so;
+	struct file *fp;
 	struct	sockopt sopt;
 
 	if (val == NULL)
@@ -1363,10 +1419,12 @@
 	}
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, s, &so, NULL)) == 0) {
+	error = getsock(td->td_proc->p_fd, s, &fp);
+	if (error == 0) {
+		so = fp->f_data;
 		error = sogetopt(so, &sopt);
 		*valsize = sopt.sopt_valsize;
-		fputsock(so);
+		fdrop(fp, td);
 	}
 	NET_UNLOCK_GIANT();
 	return (error);
@@ -1390,12 +1448,15 @@
 {
 	struct socket *so;
 	struct sockaddr *sa;
+	struct file *fp;
 	socklen_t len;
 	int error;
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, uap->fdes, &so, NULL)) != 0)
+	error = getsock(td->td_proc->p_fd, uap->fdes, &fp);
+	if (error)
 		goto done2;
+	so = fp->f_data;
 	error = copyin(uap->alen, &len, sizeof (len));
 	if (error)
 		goto done1;
@@ -1425,7 +1486,7 @@
 	if (sa)
 		FREE(sa, M_SONAME);
 done1:
-	fputsock(so);
+	fdrop(fp, td);
 done2:
 	NET_UNLOCK_GIANT();
 	return (error);
@@ -1475,12 +1536,15 @@
 {
 	struct socket *so;
 	struct sockaddr *sa;
+	struct file *fp;
 	socklen_t len;
 	int error;
 
 	NET_LOCK_GIANT();
-	if ((error = fgetsock(td, uap->fdes, &so, NULL)) != 0)
+	error = getsock(td->td_proc->p_fd, uap->fdes, &fp);
+	if (error)
 		goto done2;
+	so = fp->f_data;
 	if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
 		error = ENOTCONN;
 		goto done1;
@@ -1515,7 +1579,7 @@
 	if (sa)
 		FREE(sa, M_SONAME);
 done1:
-	fputsock(so);
+	fdrop(fp, td);
 done2:
 	NET_UNLOCK_GIANT();
 	return (error);
