Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Nov 2014 15:55:57 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r274513 - in projects/sendfile/sys: kern sys
Message-ID:  <201411141555.sAEFtvur007240@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Fri Nov 14 15:55:56 2014
New Revision: 274513
URL: https://svnweb.freebsd.org/changeset/base/274513

Log:
  When sbcut() works on M_NOTREADY mbufs, it shouldn't free them, since
  they a referenced by some outside entity. Instead, sbcut() would mark
  them with a new flag and forget them.
  
  Later, if sbready() encounters such mbufs, it frees them.
  
  Sponsored by:	Nginx, Inc.

Modified:
  projects/sendfile/sys/kern/uipc_sockbuf.c
  projects/sendfile/sys/sys/sockbuf.h

Modified: projects/sendfile/sys/kern/uipc_sockbuf.c
==============================================================================
--- projects/sendfile/sys/kern/uipc_sockbuf.c	Fri Nov 14 15:50:16 2014	(r274512)
+++ projects/sendfile/sys/kern/uipc_sockbuf.c	Fri Nov 14 15:55:56 2014	(r274513)
@@ -78,6 +78,20 @@ sbready(struct sockbuf *sb, struct mbuf 
 
 	SOCKBUF_LOCK_ASSERT(sb);
 
+	if (m->m_flags & M_SBCUTTED) {
+		/*
+		 * Oops, something bad happened to the socket buffer while
+		 * we were working on the data.  Our mbufs are detached from
+		 * the sockbuf, and all what we can do is free them.
+		 */
+		for (int i = 0; i < count; i++) {
+			KASSERT(m->m_flags & M_SBCUTTED,
+			    ("%s: m %p !M_SBCUTTED", __func__, m));
+			m = m_free(m);
+		}
+		return (EPIPE);
+	}
+
 	KASSERT(sb->sb_fnrdy != NULL, ("%s: sb %p NULL fnrdy", __func__, sb));
 
 	blocker = (sb->sb_fnrdy == m) ? M_BLOCKED : 0;
@@ -1045,8 +1059,12 @@ sbcut_internal(struct sockbuf *sb, int l
 		len -= m->m_len;
 		sbfree(sb, m);
 		n = m->m_next;
-		m->m_next = mfree;
-		mfree = m;
+		if (m->m_flags & M_NOTREADY)
+			m->m_flags |= M_SBCUTTED;
+		else {
+			m->m_next = mfree;
+			mfree = m;
+		}
 		m = n;
 	}
 	if (m) {

Modified: projects/sendfile/sys/sys/sockbuf.h
==============================================================================
--- projects/sendfile/sys/sys/sockbuf.h	Fri Nov 14 15:50:16 2014	(r274512)
+++ projects/sendfile/sys/sys/sockbuf.h	Fri Nov 14 15:55:56 2014	(r274513)
@@ -128,6 +128,7 @@ struct	sockbuf {
 #define	M_NOTREADY	M_PROTO1	/* m_data not populated yet */
 #define	M_BLOCKED	M_PROTO2	/* M_NOTREADY in front of m */
 #define	M_NOTAVAIL	(M_NOTREADY | M_BLOCKED)
+#define	M_SBCUTTED	M_PROTO3	/* mbuf was sbcutted out */
 
 void	sbappend(struct sockbuf *sb, struct mbuf *m);
 void	sbappend_locked(struct sockbuf *sb, struct mbuf *m);



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