[PATCH] knfsd: nfsd: don't drop silently on upcall deferral

To avoid tying up server threads when nfsd makes an upcall (to mountd, to get
export options, to idmapd, for nfsv4 name<->id mapping, etc.), we temporarily
"drop" the request and save enough information so that we can revisit it
later.

Certain failures during the deferral process can cause us to really drop the
request and never revisit it.

This is often less than ideal, and is unacceptable in the NFSv4 case--rfc 3530
forbids the server from dropping a request without also closing the
connection.

As a first step, we modify the deferral code to return -ETIMEDOUT (which is
translated to nfserr_jukebox in the v3 and v4 cases, and remains a drop in the
v2 case).

Signed-off-by: J. Bruce Fields <[email protected]>
Signed-off-by: Neil Brown <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
J.Bruce Fields 2006-12-13 00:35:25 -08:00 • committed by Linus Torvalds
commit e0bb89ef03
6 changed files with 22 additions and 11 deletions

View file

@ -787,15 +787,20 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
key.ex_dentry = dentry;
exp = svc_export_lookup(&key);
if (exp != NULL)
switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
if (exp != NULL) {
int err;
err = cache_check(&svc_export_cache, &exp->h, reqp);
switch (err) {
case 0: break;
case -EAGAIN:
exp = ERR_PTR(-EAGAIN);
case -ETIMEDOUT:
exp = ERR_PTR(err);
break;
default:
exp = NULL;
}
}
return exp;
}

View file

@ -169,9 +169,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
}
error = nfserr_dropit;
if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
|| PTR_ERR(exp) == -ETIMEDOUT)) {
error = nfserrno(PTR_ERR(exp));
goto out;
}
error = nfserr_stale;
if (!exp || IS_ERR(exp))

View file

@ -99,7 +99,7 @@ static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE];
/*
* Called from nfsd_lookup and encode_dirent. Check if we have crossed
* a mount point.
* Returns -EAGAIN leaving *dpp and *expp unchanged,
* Returns -EAGAIN or -ETIMEDOUT leaving *dpp and *expp unchanged,
* or nfs_ok having possibly changed *dpp and *expp
*/
int