svn commit: r275968 - head/sys/kern

Gleb Smirnoff glebius at FreeBSD.org
Sat Dec 20 22:12:05 UTC 2014


Author: glebius
Date: Sat Dec 20 22:12:04 2014
New Revision: 275968
URL: https://svnweb.freebsd.org/changeset/base/275968

Log:
  Revert r274494, r274712, r275955 and provide extra comments explaining
  why there could appear a zero-sized mbufs in socket buffers.
  
  A proper fix would be to divorce record socket buffers and stream
  socket buffers, and divorce pru_send that accepts normal data from
  pru_send that accepts control data.

Modified:
  head/sys/kern/uipc_sockbuf.c
  head/sys/kern/uipc_socket.c

Modified: head/sys/kern/uipc_sockbuf.c
==============================================================================
--- head/sys/kern/uipc_sockbuf.c	Sat Dec 20 21:17:28 2014	(r275967)
+++ head/sys/kern/uipc_sockbuf.c	Sat Dec 20 22:12:04 2014	(r275968)
@@ -640,9 +640,6 @@ sbappendstream_locked(struct sockbuf *sb
 {
 	SOCKBUF_LOCK_ASSERT(sb);
 
-	if (m == NULL)
-		return;
-
 	KASSERT(m->m_nextpkt == NULL,("sbappendstream 0"));
 	KASSERT(sb->sb_mb == sb->sb_lastrecord,("sbappendstream 1"));
 
@@ -1065,6 +1062,21 @@ sbcut_internal(struct sockbuf *sb, int l
 			m = n;
 		}
 	}
+	/*
+	 * Free any zero-length mbufs from the buffer.
+	 * For SOCK_DGRAM sockets such mbufs represent empty records.
+	 * XXX: For SOCK_STREAM sockets such mbufs can appear in the buffer,
+	 * when sosend_generic() needs to send only control data.
+	 */
+	while (m && m->m_len == 0) {
+		struct mbuf *n;
+
+		sbfree(sb, m);
+		n = m->m_next;
+		m->m_next = mfree;
+		mfree = m;
+		m = n;
+	}
 	if (m) {
 		sb->sb_mb = m;
 		m->m_nextpkt = next;

Modified: head/sys/kern/uipc_socket.c
==============================================================================
--- head/sys/kern/uipc_socket.c	Sat Dec 20 21:17:28 2014	(r275967)
+++ head/sys/kern/uipc_socket.c	Sat Dec 20 22:12:04 2014	(r275968)
@@ -1310,11 +1310,14 @@ restart:
 				resid = 0;
 				if (flags & MSG_EOR)
 					top->m_flags |= M_EOR;
-			} else if (resid > 0) {
+			} else {
 				/*
 				 * Copy the data from userland into a mbuf
-				 * chain.  If no data is to be copied in,
-				 * a single empty mbuf is returned.
+				 * chain.  If resid is 0, which can happen
+				 * only if we have control to send, then
+				 * a single empty mbuf is returned.  This
+				 * is a workaround to prevent protocol send
+				 * methods to panic.
 				 */
 				top = m_uiotombuf(uio, M_WAITOK, space,
 				    (atomic ? max_hdr : 0),


More information about the svn-src-all mailing list