Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Oct 2012 12:31:12 +0000 (UTC)
From:      Andre Oppermann <andre@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r242309 - head/sys/kern
Message-ID:  <201210291231.q9TCVCsb061085@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andre
Date: Mon Oct 29 12:31:12 2012
New Revision: 242309
URL: http://svn.freebsd.org/changeset/base/242309

Log:
  In soreceive_stream() don't drop an already dequeued mbuf chain by
  overwriting the return mbuf pointer with newly received data after
  a loop.  Instead append the new mbuf chain to the existing one.
  
  Fix up sb_lastrecord when dequeuing mbuf's so that sbappend_stream()
  doesn't get confused.
  
  For the remainder copy case in the mbuf delivery part deduct the
  copied length len instead of the whole mbuf length.  Additionally
  don't depend on 'n' being being available which isn't true in the
  case of MSG_PEEK.
  
  Fix the MSG_WAITALL case by comparing against sb_hiwat.  Before
  it was looping for every receive as sb_lowat normally is zero.
  Add comment about issue with (MSG_WAITALL | MSG_PEEK) which isn't
  properly handled.
  
  Submitted by:	trociny (except for the change in last paragraph)

Modified:
  head/sys/kern/uipc_socket.c

Modified: head/sys/kern/uipc_socket.c
==============================================================================
--- head/sys/kern/uipc_socket.c	Mon Oct 29 12:17:02 2012	(r242308)
+++ head/sys/kern/uipc_socket.c	Mon Oct 29 12:31:12 2012	(r242309)
@@ -1962,6 +1962,7 @@ release:
 
 /*
  * Optimized version of soreceive() for stream (TCP) sockets.
+ * XXXAO: (MSG_WAITALL | MSG_PEEK) isn't properly handled.
  */
 int
 soreceive_stream(struct socket *so, struct sockaddr **psa, struct uio *uio,
@@ -2050,7 +2051,7 @@ restart:
 
 	/* On MSG_WAITALL we must wait until all data or error arrives. */
 	if ((flags & MSG_WAITALL) &&
-	    (sb->sb_cc >= uio->uio_resid || sb->sb_cc >= sb->sb_lowat))
+	    (sb->sb_cc >= uio->uio_resid || sb->sb_cc >= sb->sb_hiwat))
 		goto deliver;
 
 	/*
@@ -2076,7 +2077,11 @@ deliver:
 	if (mp0 != NULL) {
 		/* Dequeue as many mbufs as possible. */
 		if (!(flags & MSG_PEEK) && len >= sb->sb_mb->m_len) {
-			for (*mp0 = m = sb->sb_mb;
+			if (*mp0 == NULL)
+				*mp0 = sb->sb_mb;
+			else
+				m_cat(*mp0, sb->sb_mb);
+			for (m = sb->sb_mb;
 			     m != NULL && m->m_len <= len;
 			     m = m->m_next) {
 				len -= m->m_len;
@@ -2084,10 +2089,11 @@ deliver:
 				sbfree(sb, m);
 				n = m;
 			}
+			n->m_next = NULL;
 			sb->sb_mb = m;
+			sb->sb_lastrecord = sb->sb_mb;
 			if (sb->sb_mb == NULL)
 				SB_EMPTY_FIXUP(sb);
-			n->m_next = NULL;
 		}
 		/* Copy the remainder. */
 		if (len > 0) {
@@ -2098,9 +2104,9 @@ deliver:
 			if (m == NULL)
 				len = 0;	/* Don't flush data from sockbuf. */
 			else
-				uio->uio_resid -= m->m_len;
+				uio->uio_resid -= len;
 			if (*mp0 != NULL)
-				n->m_next = m;
+				m_cat(*mp0, m);
 			else
 				*mp0 = m;
 			if (*mp0 == NULL) {



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