At 12:24 PM -0800 12/16/01, Matthew Dillon wrote:
> program runs fine in an overnight test. We still have a known issue
> with out-of-order operations from nfsiod's that apparently may come
> up after a week or so of testing. I asked Jordan to try to track down
> the NeXT guy who fixed that one in the old NFS stack.
This bug showed up recently here with fsx testing. I seem to have fixed it
last week in MacOS X. The diffs were widespread but the idea was simple
enough so a few code snippets should suffice:
nfs_request gets a new argument (u_int64_t *xidp) and fills it in here:
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
if (xidp)
*xidp = xid + ((u_int64_t)nfs_xidwrap << 32);
nfsm_rpchead bumps nfs_xidwrap when avoiding a zero xid.
Callers of nfs_request take the returned xid and pass it via the macros to
nfs_loadattrcache, from which the following code is snipped:
if (*xidp < np->n_xid) {
/*
* We have already updated attributes with a response from
* a later request. The attributes we have here are probably
* stale so we drop them (just return). However, our
* out-of-order receipt could be correct - if the requests were
* processed out of order at the server. Given the uncertainty
* we invalidate our cached attributes. *xidp is zeroed here
* to indicate the attributes were dropped - only getattr
* cares - it needs to retry the rpc.
*/
np->n_attrstamp = 0;
*xidp = 0;
return (0);
}
Further down in nfs_loadattrcache:
np->n_xid = *xidp;
Note xids are kept in a 64 bit form so relative comparison won't fail in
the unlikely case that xids wrap around zero.
Here's the change in nfs_getattr. I don't expect to ever see the panic.
avoidfloods = 0;
tryagain:
nfsstats.rpccnt[NFSPROC_GETATTR]++;
nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
nfsm_fhtom(vp, v3);
nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred, &xid);
if (!error) {
nfsm_loadattr(vp, ap->a_vap, &xid);
if (!xid) { /* out-of-order rpc - attributes were dropped */
m_freem(mrep);
if (avoidfloods++ < 100)
goto tryagain;
/*
* avoidfloods>1 is bizarre. at 100 pull the plug
*/
panic("nfs_getattr: getattr flood\n");
}
--
Conrad Minshall, [EMAIL PROTECTED], 408 974-2749
Apple Computer, Mac OS X Core Operating Systems
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message