diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-04-11 18:44:25 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-04-11 18:44:25 +0000 |
commit | 651914aea01f85314bd7fcd839741339ede35fa8 (patch) | |
tree | 8b526f9eb62819db56f3b8cac9fc52952cc59453 /sys | |
parent | 42d3e35e7b9eeb9be5ec1445206b35f3b81a59d8 (diff) |
Back out nfs_realign() change, it causes "pool_get: must have NOWAIT" panics.
deraadt@ OK
Diffstat (limited to 'sys')
-rw-r--r-- | sys/nfs/nfs_socket.c | 122 |
1 files changed, 86 insertions, 36 deletions
diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c index fb12bf9258b..2f5a353eab9 100644 --- a/sys/nfs/nfs_socket.c +++ b/sys/nfs/nfs_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_socket.c,v 1.25 2002/04/10 18:16:46 csapuntz Exp $ */ +/* $OpenBSD: nfs_socket.c,v 1.26 2002/04/11 18:44:24 millert Exp $ */ /* $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $ */ /* @@ -136,9 +136,7 @@ static int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, }; int nfsrtton = 0; struct nfsrtt nfsrtt; -void nfs_realign(struct mbuf **, int); -unsigned int nfs_realign_test = 0; -unsigned int nfs_realign_count = 0; +void nfs_realign(struct mbuf *, int); /* * Initialize sockets and congestion for a new NFS connection. @@ -532,7 +530,6 @@ tryagain: } if (error) goto errout; - len = ntohl(len) & ~0x80000000; /* * This is SERIOUS! We are out of sync with the sender @@ -633,7 +630,7 @@ errout: * These could cause pointer alignment problems, so copy them to * well aligned mbufs. */ - nfs_realign(mp, 5 * NFSX_UNSIGNED); + nfs_realign(*mp, 5 * NFSX_UNSIGNED); return (error); } @@ -1445,44 +1442,97 @@ nfs_rcvunlock(flagp) } /* - * NFS parsing code requires 32-bit alignment + * Check for badly aligned mbuf data areas and + * realign data in an mbuf list by copying the data areas up, as required. */ void -nfs_realign(struct mbuf **pm, int hsiz) -{ +nfs_realign(m, hsiz) struct mbuf *m; - struct mbuf *n = NULL; - int off = 0; - - ++nfs_realign_test; - while ((m = *pm) != NULL) { - if ((m->m_len & 0x3) || (mtod(m, long) & 0x3)) { - MGET(n, M_WAIT, MT_DATA); - if (m->m_len >= MINCLSIZE) { - MCLGET(n, M_WAIT); - } - n->m_len = 0; - break; + int hsiz; +{ + struct mbuf *m2; + int siz, mlen, olen; + caddr_t tcp, fcp; + struct mbuf *mnew; + + while (m) { + /* + * This never happens for UDP, rarely happens for TCP + * but frequently happens for iso transport. + */ + if ((m->m_len & 0x3) || (mtod(m, long) & 0x3)) { + olen = m->m_len; + fcp = mtod(m, caddr_t); + if ((long)fcp & 0x3) { + if (m->m_flags & M_PKTHDR) + m_tag_delete_chain(m, NULL); + m->m_flags &= ~M_PKTHDR; + if (m->m_flags & M_EXT) + m->m_data = m->m_ext.ext_buf + + ((m->m_ext.ext_size - olen) & ~0x3); + else + m->m_data = m->m_dat; } - pm = &m->m_next; - } - /* - * If n is non-NULL, loop on m copying data, then replace the - * portion of the chain that had to be realigned. - */ - if (n != NULL) { - ++nfs_realign_count; + m->m_len = 0; + tcp = mtod(m, caddr_t); + mnew = m; + m2 = m->m_next; + + /* + * If possible, only put the first invariant part + * of the RPC header in the first mbuf. + */ + mlen = M_TRAILINGSPACE(m); + if (olen <= hsiz && mlen > hsiz) + mlen = hsiz; + + /* Loop through the mbuf list consolidating data. */ while (m) { - m_copyback(n, off, m->m_len, mtod(m, caddr_t)); - off += m->m_len; + while (olen > 0) { + if (mlen == 0) { + if (m2->m_flags & M_PKTHDR) + m_tag_delete_chain(m2, NULL); + m2->m_flags &= ~M_PKTHDR; + if (m2->m_flags & M_EXT) + m2->m_data = m2->m_ext.ext_buf; + else + m2->m_data = m2->m_dat; + m2->m_len = 0; + mlen = M_TRAILINGSPACE(m2); + tcp = mtod(m2, caddr_t); + mnew = m2; + m2 = m2->m_next; + } + siz = min(mlen, olen); + if (tcp != fcp) + bcopy(fcp, tcp, siz); + mnew->m_len += siz; + mlen -= siz; + olen -= siz; + tcp += siz; + fcp += siz; + } m = m->m_next; + if (m) { + olen = m->m_len; + fcp = mtod(m, caddr_t); + } } - m_freem(*pm); - *pm = n; + + /* + * Finally, set m_len == 0 for any trailing mbufs that have + * been copied out of. + */ + while (m2) { + m2->m_len = 0; + m2 = m2->m_next; + } + return; + } + m = m->m_next; } } - /* * Parse an RPC request * - verify it @@ -1837,7 +1887,7 @@ nfsrv_rcv(so, arg, waitflag) error = soreceive(so, &nam, &auio, &mp, (struct mbuf **)0, &flags); if (mp) { - nfs_realign(&mp, 10 * NFSX_UNSIGNED); + nfs_realign(mp, 10 * NFSX_UNSIGNED); if (nam) { m = nam; m->m_next = mp; @@ -1981,7 +2031,7 @@ nfsrv_getstream(slp, waitflag) mpp = &((*mpp)->m_next); *mpp = recm; if (slp->ns_flag & SLP_LASTFRAG) { - nfs_realign(&slp->ns_frag, 10 * NFSX_UNSIGNED); + nfs_realign(slp->ns_frag, 10 * NFSX_UNSIGNED); if (slp->ns_recend) slp->ns_recend->m_nextpkt = slp->ns_frag; else |