summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2002-04-11 18:44:25 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2002-04-11 18:44:25 +0000
commit651914aea01f85314bd7fcd839741339ede35fa8 (patch)
tree8b526f9eb62819db56f3b8cac9fc52952cc59453 /sys
parent42d3e35e7b9eeb9be5ec1445206b35f3b81a59d8 (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.c122
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