Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Jun 2013 03:08:02 +0000 (UTC)
From:      Lawrence Stewart <lstewart@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r251984 - head/sys/kern
Message-ID:  <201306190308.r5J382xs031123@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: lstewart
Date: Wed Jun 19 03:08:01 2013
New Revision: 251984
URL: http://svnweb.freebsd.org/changeset/base/251984

Log:
  When a previous call to sbsndptr() leaves sb->sb_sndptroff at the start of an
  mbuf that was fully consumed by the previous call, the mbuf ptr returned by the
  current call ends up being the previous mbuf in the sb chain to the one that
  contains the data we want.
  
  This does not cause any observable issues because the mbuf copy routines happily
  walk the mbuf chain to get to the data at the moff offset, which in this case
  means they effectively skip over the mbuf returned by sbsndptr().
  
  We can't adjust sb->sb_sndptr during the previous call for this case because the
  next mbuf in the chain may not exist yet. We therefore need to detect the
  condition and make the adjustment during the current call.
  
  Fix by detecting the special case of moff being at the start of the next mbuf in
  the chain and adjust the required accounting variables accordingly.
  
  Reviewed by:	andre
  MFC after:	2 weeks

Modified:
  head/sys/kern/uipc_sockbuf.c

Modified: head/sys/kern/uipc_sockbuf.c
==============================================================================
--- head/sys/kern/uipc_sockbuf.c	Wed Jun 19 02:30:32 2013	(r251983)
+++ head/sys/kern/uipc_sockbuf.c	Wed Jun 19 03:08:01 2013	(r251984)
@@ -942,6 +942,13 @@ sbsndptr(struct sockbuf *sb, u_int off, 
 	/* Return closest mbuf in chain for current offset. */
 	*moff = off - sb->sb_sndptroff;
 	m = ret = sb->sb_sndptr ? sb->sb_sndptr : sb->sb_mb;
+	if (*moff == m->m_len) {
+		*moff = 0;
+		sb->sb_sndptroff += m->m_len;
+		m = ret = m->m_next;
+		KASSERT(ret->m_len > 0,
+		    ("mbuf %p in sockbuf %p chain has no valid data", ret, sb));
+	}
 
 	/* Advance by len to be as close as possible for the next transmit. */
 	for (off = off - sb->sb_sndptroff + len - 1;



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