Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 May 2000 12:38:23 -0700 (PDT)
From:      Archie Cobbs <archie@whistle.com>
To:        freebsd-net@freebsd.org
Cc:        freebsd-hackers@freebsd.org
Subject:   panic reading routing socket
Message-ID:  <200005081938.MAA03269@bubba.whistle.com>

next in thread | raw e-mail | index | archive | help
The patch below adds some INVARIANTS consistency checks to socket
receive operations. This was motivated by a recurring "receive 1"
panic that happens every couple of weeks on a 3.4-RELEASE based
system.

When I use this patch I get an immediate panic as the system comes
up, when routed tries to read the routing socket (line 724 of
uipc_socket.c (3.4-REL post patch)).

But I can't figure out if the panic is occurring because the patch
is bogus (i.e., checking too stringently) or if there really is a
bug in there somewhere.

Any thoughts appreciated..

Thanks,
-Archie

___________________________________________________________________________
Archie Cobbs   *   Whistle Communications, Inc.  *   http://www.whistle.com

diff -ur /usr/src/sys/kern/uipc_socket.c ./uipc_socket.c
--- /usr/src/sys/kern/uipc_socket.c	Sun Aug 29 09:26:11 1999
+++ ./uipc_socket.c	Mon May  8 11:44:21 2000
@@ -55,6 +55,21 @@
 
 #include <machine/limits.h>
 
+#ifdef INVARIANTS
+#define SPLNETCHECK()	do {				\
+		int s1, s2;				\
+		s1 = splnet();				\
+		s2 = splnet();				\
+		if (s1 != s2)				\
+		    panic("%s: !splnet", __FUNCTION__);	\
+		splx(s1);				\
+	} while (0)
+#define SBCHECK(sb)	sbcheck(sb)
+#else
+#define SPLNETCHECK()	do { } while (0)
+#define SBCHECK(so)	do { } while (0)
+#endif
+
 struct	vm_zone *socket_zone;
 so_gen_t	so_gencnt;	/* generation count for sockets */
 
@@ -629,6 +644,7 @@
 	if (error)
 		return (error);
 	s = splnet();
+	SBCHECK(&so->so_rcv);
 
 	m = so->so_rcv.sb_mb;
 	/*
@@ -678,6 +694,7 @@
 			error = EWOULDBLOCK;
 			goto release;
 		}
+		SBCHECK(&so->so_rcv);
 		sbunlock(&so->so_rcv);
 		error = sbwait(&so->so_rcv);
 		splx(s);
@@ -686,6 +703,7 @@
 		goto restart;
 	}
 dontblock:
+	SBCHECK(&so->so_rcv);
 	if (uio->uio_procp)
 		uio->uio_procp->p_stats->p_ru.ru_msgrcv++;
 	nextrecord = m->m_nextpkt;
@@ -695,6 +713,7 @@
 		if (psa)
 			*psa = dup_sockaddr(mtod(m, struct sockaddr *),
 					    mp0 == 0);
+		SBCHECK(&so->so_rcv);
 		if (flags & MSG_PEEK) {
 			m = m->m_next;
 		} else {
@@ -702,8 +721,10 @@
 			MFREE(m, so->so_rcv.sb_mb);
 			m = so->so_rcv.sb_mb;
 		}
+		SBCHECK(&so->so_rcv);
 	}
 	while (m && m->m_type == MT_CONTROL && error == 0) {
+		SBCHECK(&so->so_rcv);
 		if (flags & MSG_PEEK) {
 			if (controlp)
 				*controlp = m_copy(m, 0, m->m_len);
@@ -724,6 +745,7 @@
 				m = so->so_rcv.sb_mb;
 			}
 		}
+		SBCHECK(&so->so_rcv);
 		if (controlp) {
 			orig_resid = 0;
 			controlp = &(*controlp)->m_next;
@@ -736,6 +758,7 @@
 		if (type == MT_OOBDATA)
 			flags |= MSG_OOB;
 	}
+	SBCHECK(&so->so_rcv);
 	moff = 0;
 	offset = 0;
 	while (m && uio->uio_resid > 0 && error == 0) {
@@ -762,13 +785,16 @@
 		 * block interrupts again.
 		 */
 		if (mp == 0) {
+			SBCHECK(&so->so_rcv);
 			splx(s);
 			error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
 			s = splnet();
+			SBCHECK(&so->so_rcv);
 			if (error)
 				goto release;
 		} else
 			uio->uio_resid -= len;
+		SBCHECK(&so->so_rcv);
 		if (len == m->m_len - moff) {
 			if (m->m_flags & M_EOR)
 				flags |= MSG_EOR;
@@ -801,6 +827,7 @@
 				so->so_rcv.sb_cc -= len;
 			}
 		}
+		SBCHECK(&so->so_rcv);
 		if (so->so_oobmark) {
 			if ((flags & MSG_PEEK) == 0) {
 				so->so_oobmark -= len;
@@ -814,6 +841,7 @@
 					break;
 			}
 		}
+		SBCHECK(&so->so_rcv);
 		if (flags & MSG_EOR)
 			break;
 		/*
@@ -837,19 +865,23 @@
 			if (m)
 				nextrecord = m->m_nextpkt;
 		}
+		SBCHECK(&so->so_rcv);
 	}
 
+	SBCHECK(&so->so_rcv);
 	if (m && pr->pr_flags & PR_ATOMIC) {
 		flags |= MSG_TRUNC;
 		if ((flags & MSG_PEEK) == 0)
 			(void) sbdroprecord(&so->so_rcv);
 	}
+	SBCHECK(&so->so_rcv);
 	if ((flags & MSG_PEEK) == 0) {
 		if (m == 0)
 			so->so_rcv.sb_mb = nextrecord;
 		if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
 			(*pr->pr_usrreqs->pru_rcvd)(so, flags);
 	}
+	SBCHECK(&so->so_rcv);
 	if (orig_resid == uio->uio_resid && orig_resid &&
 	    (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
 		sbunlock(&so->so_rcv);
@@ -860,6 +892,7 @@
 	if (flagsp)
 		*flagsp |= flags;
 release:
+	SBCHECK(&so->so_rcv);
 	sbunlock(&so->so_rcv);
 	splx(s);
 	return (error);
diff -ur /usr/src/sys/kern/uipc_socket2.c ./uipc_socket2.c
--- /usr/src/sys/kern/uipc_socket2.c	Fri Oct  1 10:08:50 1999
+++ ./uipc_socket2.c	Mon May  8 11:45:43 2000
@@ -48,6 +48,21 @@
 #include <sys/signalvar.h>
 #include <sys/sysctl.h>
 
+#ifdef INVARIANTS
+#define SPLNETCHECK()	do {				\
+		int s1, s2;				\
+		s1 = splnet();				\
+		s2 = splnet();				\
+		if (s1 != s2)				\
+		    panic("%s: !splnet", __FUNCTION__);	\
+		splx(s1);				\
+	} while (0)
+#define SBCHECK(sb)	sbcheck(sb)
+#else
+#define SPLNETCHECK()	do { } while (0)
+#define SBCHECK(so)	do { } while (0)
+#endif
+
 /*
  * Primitive routines for operating on sockets and socket buffers
  */
@@ -301,6 +316,7 @@
 			return (error);
 	}
 	sb->sb_flags |= SB_LOCK;
+	SBCHECK(sb);
 	return (0);
 }
 
@@ -450,6 +466,7 @@
 {
 	register struct mbuf *n;
 
+	SPLNETCHECK();
 	if (m == 0)
 		return;
 	n = sb->sb_mb;
@@ -466,7 +483,7 @@
 	sbcompress(sb, m, n);
 }
 
-#ifdef SOCKBUF_DEBUG
+#ifdef INVARIANT_SUPPORT
 void
 sbcheck(sb)
 	register struct sockbuf *sb;
@@ -475,6 +492,7 @@
 	register struct mbuf *n = 0;
 	register u_long len = 0, mbcnt = 0;
 
+	SPLNETCHECK();
 	for (m = sb->sb_mb; m; m = n) {
 	    n = m->m_nextpkt;
 	    for (; m; m = m->m_next) {
@@ -490,7 +508,7 @@
 		panic("sbcheck");
 	}
 }
-#endif
+#endif /* INVARIANT_SUPPORT */
 
 /*
  * As above, except the mbuf chain
@@ -503,6 +521,7 @@
 {
 	register struct mbuf *m;
 
+	SPLNETCHECK();
 	if (m0 == 0)
 		return;
 	m = sb->sb_mb;
@@ -540,6 +559,7 @@
 	register struct mbuf *m;
 	register struct mbuf **mp;
 
+	SPLNETCHECK();
 	if (m0 == 0)
 		return;
 	for (mp = &sb->sb_mb; *mp ; mp = &((*mp)->m_nextpkt)) {
@@ -588,8 +608,8 @@
 	register struct mbuf *m, *n;
 	int space = asa->sa_len;
 
-if (m0 && (m0->m_flags & M_PKTHDR) == 0)
-panic("sbappendaddr");
+	KASSERT(!m0 || (m0->m_flags & M_PKTHDR) != 0, ("sbappendaddr"));
+	SBCHECK(sb);
 	if (m0)
 		space += m0->m_pkthdr.len;
 	for (n = control; n; n = n->m_next) {
@@ -620,6 +640,7 @@
 		n->m_nextpkt = m;
 	} else
 		sb->sb_mb = m;
+	SBCHECK(sb);
 	return (1);
 }
 
@@ -631,6 +652,7 @@
 	register struct mbuf *m, *n;
 	int space = 0;
 
+	SBCHECK(sb);
 	if (control == 0)
 		panic("sbappendcontrol");
 	for (m = control; ; m = m->m_next) {
@@ -653,6 +675,7 @@
 		n->m_nextpkt = control;
 	} else
 		sb->sb_mb = control;
+	SBCHECK(sb);
 	return (1);
 }
 
@@ -669,6 +692,7 @@
 	register int eor = 0;
 	register struct mbuf *o;
 
+	SBCHECK(sb);
 	while (m) {
 		eor |= m->m_flags & M_EOR;
 		if (m->m_len == 0 &&
@@ -704,6 +728,7 @@
 		else
 			printf("semi-panic: sbcompress\n");
 	}
+	SBCHECK(sb);
 }
 
 /*
@@ -741,6 +766,7 @@
 	register struct mbuf *m, *mn;
 	struct mbuf *next;
 
+	SBCHECK(sb);
 	next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
 	while (len > 0) {
 		if (m == 0) {
@@ -771,6 +797,7 @@
 		m->m_nextpkt = next;
 	} else
 		sb->sb_mb = next;
+	SBCHECK(sb);
 }
 
 /*
@@ -783,6 +810,7 @@
 {
 	register struct mbuf *m, *mn;
 
+	SBCHECK(sb);
 	m = sb->sb_mb;
 	if (m) {
 		sb->sb_mb = m->m_nextpkt;
@@ -792,6 +820,7 @@
 			m = mn;
 		} while (m);
 	}
+	SBCHECK(sb);
 }
 
 /*


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




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