From owner-freebsd-net Mon May 8 12:38:43 2000 Delivered-To: freebsd-net@freebsd.org Received: from bubba.whistle.com (bubba.whistle.com [207.76.205.7]) by hub.freebsd.org (Postfix) with ESMTP id 9E32737BBF9; Mon, 8 May 2000 12:38:24 -0700 (PDT) (envelope-from archie@whistle.com) Received: (from archie@localhost) by bubba.whistle.com (8.9.3/8.9.2) id MAA03269; Mon, 8 May 2000 12:38:23 -0700 (PDT) From: Archie Cobbs Message-Id: <200005081938.MAA03269@bubba.whistle.com> Subject: panic reading routing socket To: freebsd-net@freebsd.org Date: Mon, 8 May 2000 12:38:23 -0700 (PDT) Cc: freebsd-hackers@freebsd.org X-Mailer: ELM [version 2.4ME+ PL54 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org 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 +#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 #include +#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