svn commit: r248830 - head/sys/kern

Scott Long scottl at FreeBSD.org
Thu Mar 28 14:14:29 UTC 2013


Author: scottl
Date: Thu Mar 28 14:14:28 2013
New Revision: 248830
URL: http://svnweb.freebsd.org/changeset/base/248830

Log:
  Several fixes and improvements to sendfile()
  
  1.  If we wanted to send exactly as many bytes as the socket buffer is
      sized for, the inner loop of kern_sendfile() would see that the
      socket is full before seeing that it had no more bytes left to send.
      This would cause it to return EAGAIN to the caller instead of
      success.  Fix by changing the order that these conditions are tested.
  2.  Simplify the calculation for the bytes to send in each iteration of
      the inner loop of kern_sendfile()
  3.  Fix some calls with bogus arguments to sf_buf_ext().  These would
      only trigger on mbuf allocation failure, but would be hilariously
      bad if they did trigger.
  
  Submitted by:	gibbs(3), andre(2)
  Reviewed by:	emax, andre
  Obtained from:	Netflix
  MFC after:	1 week

Modified:
  head/sys/kern/uipc_syscalls.c

Modified: head/sys/kern/uipc_syscalls.c
==============================================================================
--- head/sys/kern/uipc_syscalls.c	Thu Mar 28 13:45:45 2013	(r248829)
+++ head/sys/kern/uipc_syscalls.c	Thu Mar 28 14:14:28 2013	(r248830)
@@ -2115,7 +2115,7 @@ retry_space:
 		 * Loop and construct maximum sized mbuf chain to be bulk
 		 * dumped into socket buffer.
 		 */
-		while (space > loopbytes) {
+		while (1) {
 			vm_pindex_t pindex;
 			vm_offset_t pgoff;
 			struct mbuf *m0;
@@ -2127,15 +2127,12 @@ retry_space:
 			 * or the passed in nbytes.
 			 */
 			pgoff = (vm_offset_t)(off & PAGE_MASK);
-			xfsize = omin(PAGE_SIZE - pgoff,
-			    obj->un_pager.vnp.vnp_size - uap->offset -
-			    fsbytes - loopbytes);
 			if (uap->nbytes)
 				rem = (uap->nbytes - fsbytes - loopbytes);
 			else
 				rem = obj->un_pager.vnp.vnp_size -
 				    uap->offset - fsbytes - loopbytes;
-			xfsize = omin(rem, xfsize);
+			xfsize = omin(PAGE_SIZE - pgoff, rem);
 			xfsize = omin(space - loopbytes, xfsize);
 			if (xfsize <= 0) {
 				VM_OBJECT_WUNLOCK(obj);
@@ -2144,6 +2141,16 @@ retry_space:
 			}
 
 			/*
+			 * We've already overfilled the socket.
+			 * Let the outer loop figure out how to handle it.
+			 */
+			if (space <= loopbytes) {
+				VM_OBJECT_WUNLOCK(obj);
+				done = 0;
+				break;
+			}
+
+			/*
 			 * Attempt to look up the page.  Allocate
 			 * if not found or wait and loop if busy.
 			 */
@@ -2249,14 +2256,14 @@ retry_space:
 			m0 = m_get((mnw ? M_NOWAIT : M_WAITOK), MT_DATA);
 			if (m0 == NULL) {
 				error = (mnw ? EAGAIN : ENOBUFS);
-				sf_buf_mext((void *)sf_buf_kva(sf), sf);
+				sf_buf_mext(NULL, sf);
 				break;
 			}
 			if (m_extadd(m0, (caddr_t )sf_buf_kva(sf), PAGE_SIZE,
 			    sf_buf_mext, sfs, sf, M_RDONLY, EXT_SFBUF,
 			    (mnw ? M_NOWAIT : M_WAITOK)) != 0) {
 				error = (mnw ? EAGAIN : ENOBUFS);
-				sf_buf_mext((void *)sf_buf_kva(sf), sf);
+				sf_buf_mext(NULL, sf);
 				m_freem(m0);
 				break;
 			}


More information about the svn-src-all mailing list