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 [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to