Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Jan 2004 19:41:03 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 46164 for review
Message-ID:  <200401300341.i0U3f32d099120@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=46164

Change 46164 by sam@sam_ebb on 2004/01/29 19:40:04

	add (very suboptimal) locking of do_sendfile

Affected files ...

.. //depot/projects/netperf+sockets/sys/kern/uipc_syscalls.c#9 edit

Differences ...

==== //depot/projects/netperf+sockets/sys/kern/uipc_syscalls.c#9 (text+ko) ====

@@ -1683,7 +1683,7 @@
 	struct writev_args nuap;
 	struct sf_hdtr hdtr;
 	off_t off, xfsize, hdtr_size, sbytes = 0;
-	int error, s;
+	int error;
 
 	mtx_lock(&Giant);
 
@@ -1692,7 +1692,8 @@
 	/*
 	 * The descriptor must be a regular file and have a backing VM object.
 	 */
-	if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
+	error = fgetvp_read(td, uap->fd, &vp);
+	if (error != 0)
 		goto done;
 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 	if (vp->v_type != VREG || VOP_GETVOBJECT(vp, &obj) != 0) {
@@ -1750,6 +1751,7 @@
 	/*
 	 * Protect against multiple writers to the socket.
 	 */
+	SOCKBUF_LOCK(&so->so_snd);
 	(void) sblock(&so->so_snd, M_WAITOK);
 
 	/*
@@ -1763,6 +1765,11 @@
 		vm_offset_t pgoff;
 
 		pindex = OFF_TO_IDX(off);
+		/*
+		 * XXX too many places where we can block
+		 * XXX to make it worth holding the lock
+		 */
+		SOCKBUF_UNLOCK(&so->so_snd);
 		VM_OBJECT_LOCK(obj);
 retry_lookup:
 		/*
@@ -1778,8 +1785,10 @@
 			xfsize = PAGE_SIZE - pgoff;
 		if (uap->nbytes && xfsize > (uap->nbytes - sbytes))
 			xfsize = uap->nbytes - sbytes;
-		if (xfsize <= 0)
-			break;
+		if (xfsize <= 0) {
+			SOCKBUF_LOCK(&so->so_snd);
+			goto unlock;
+		}
 		/*
 		 * Optimize the non-blocking case by looking at the socket space
 		 * before going to the extra work of constituting the sf_buf.
@@ -1789,8 +1798,8 @@
 				error = EPIPE;
 			else
 				error = EAGAIN;
-			sbunlock(&so->so_snd);
-			goto done;
+			SOCKBUF_LOCK(&so->so_snd);
+			goto unlock;
 		}
 		VM_OBJECT_LOCK(obj);
 		/*
@@ -1873,8 +1882,8 @@
 				}
 				vm_page_unlock_queues();
 				VM_OBJECT_UNLOCK(obj);
-				sbunlock(&so->so_snd);
-				goto done;
+				SOCKBUF_LOCK(&so->so_snd);
+				goto unlock;
 			}
 			mbstat.sf_iocnt++;
 		} else {
@@ -1893,9 +1902,8 @@
 			if (pg->wire_count == 0 && pg->object == NULL)
 				vm_page_free(pg);
 			vm_page_unlock_queues();
-			sbunlock(&so->so_snd);
 			error = EINTR;
-			goto done;
+			goto unlock;
 		}
 
 		/*
@@ -1905,8 +1913,8 @@
 		if (m == NULL) {
 			error = ENOBUFS;
 			sf_buf_free((void *)sf_buf_kva(sf), sf);
-			sbunlock(&so->so_snd);
-			goto done;
+			SOCKBUF_LOCK(&so->so_snd); /* XXX */
+			goto unlock;
 		}
 		/*
 		 * Setup external storage for mbuf.
@@ -1918,7 +1926,7 @@
 		/*
 		 * Add the buffer to the socket buffer chain.
 		 */
-		s = splnet();
+		SOCKBUF_LOCK(&so->so_snd);
 retry_space:
 		/*
 		 * Make sure that the socket is still able to take more data.
@@ -1939,9 +1947,7 @@
 				so->so_error = 0;
 			}
 			m_freem(m);
-			sbunlock(&so->so_snd);
-			splx(s);
-			goto done;
+			goto unlock;
 		}
 		/*
 		 * Wait for socket space to become available. We do this just
@@ -1951,10 +1957,8 @@
 		if (sbspace(&so->so_snd) < so->so_snd.sb_lowat) {
 			if (so->so_state & SS_NBIO) {
 				m_freem(m);
-				sbunlock(&so->so_snd);
-				splx(s);
 				error = EAGAIN;
-				goto done;
+				goto unlock;
 			}
 			error = sbwait(&so->so_snd);
 			/*
@@ -1964,25 +1968,22 @@
 			 */
 			if (error) {
 				m_freem(m);
-				sbunlock(&so->so_snd);
-				splx(s);
-				goto done;
+				goto unlock;
 			}
 			goto retry_space;
 		}
 		error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, td);
-		splx(s);
-		if (error) {
-			sbunlock(&so->so_snd);
-			goto done;
-		}
+		if (error)
+			goto unlock;
 	}
+unlock:
 	sbunlock(&so->so_snd);
+	SOCKBUF_UNLOCK(&so->so_snd);
 
 	/*
 	 * Send trailers. Wimp out and use writev(2).
 	 */
-	if (uap->hdtr != NULL && hdtr.trailers != NULL) {
+	if (uap->hdtr != NULL && hdtr.trailers != NULL && error == 0) {
 			nuap.fd = uap->s;
 			nuap.iovp = hdtr.trailers;
 			nuap.iovcnt = hdtr.trl_cnt;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200401300341.i0U3f32d099120>