[8170] in Athena Bugs
NFS server crashes
daemon@ATHENA.MIT.EDU (John Carr)
Thu Sep 12 00:13:54 1991
To: ops@ATHENA.MIT.EDU, bugs@ATHENA.MIT.EDU
Cc: roden@ATHENA.MIT.EDU, cec@ATHENA.MIT.EDU
Date: Thu, 12 Sep 91 00:13:56 EDT
From: John Carr <jfc@ATHENA.MIT.EDU>
The cause of the recent NFS server crashes ("mbuf map full") appears to be
the RS/6000s. Each time an RS/6000 mounts an NFS filesystem it send an RPC
request which our servers don't support. This is probably the AIX acl
request (AIX 3.1 supports file acls; when it mounts an NFS filesystem it
does RPC calls to get the acl). There is a memory leak in our NFS kernels
when bad RPC requests are received. Each NFS mount from an RS/6000 causes a
loss of 14 mbufs. When about 2500 mbufs are allocated, the server crashes.
As I write this, cyrus is very close to crashing (2302 mbufs allocated).
The good news is that this is fixable on the server side (i.e. we don't have
to modify the RS/6000 software). I believe the bug is in this section of
code in sys/rpc/svc.c:svc_getreq():
for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
if (s->sc_prog == r.rq_prog) {
if (s->sc_vers == r.rq_vers) {
(*s->sc_dispatch)(&r, xprt);
goto call_done;
} /* found correct version */
prog_found = TRUE;
if (s->sc_vers < low_vers)
low_vers = s->sc_vers;
if (s->sc_vers > high_vers)
high_vers = s->sc_vers;
} /* found correct program */
}
/*
* if we got here, the program or version
* is not served ...
*/
if (prog_found)
svcerr_progvers(xprt,
low_vers, high_vers);
else
svcerr_noprog(xprt);
/* Fall through to ... */
}
call_done:
if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
SVC_DESTROY(xprt);
break;
}
} while (stat == XPRT_MOREREQS);
SVC_STAT always returns XPRT_IDLE for transport type kudp, so SVC_DESTROY is
never called. Proposed fix: add these lines just before the comment "Fall
through to ...":
#ifdef KERNEL
/* transport type kudp always returns stat
XPRT_IDLE, so destroy will not be called
below. Call it here so that invalid
program/version combinations don't cause
memory leaks. */
SVC_DESTROY(xprt);
#endif