nfsd: Retry once in nfsd_open on an -EOPENSTALE return

If we get back -EOPENSTALE from an NFSv4 open, then we either got some
unhandled error or the inode we got back was not the same as the one
associated with the dentry.

We really have no recourse in that situation other than to retry the
open, and if it fails to just return nfserr_stale back to the client.

Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
Signed-off-by: Lance Shelton <lance.shelton@hammerspace.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
Jeff Layton 2021-12-18 20:37:56 -05:00 committed by Chuck Lever
parent a2694e51f6
commit 12bcbd40fd
2 changed files with 10 additions and 1 deletions

View File

@ -875,6 +875,7 @@ nfserrno (int errno)
{ nfserr_serverfault, -ESERVERFAULT }, { nfserr_serverfault, -ESERVERFAULT },
{ nfserr_serverfault, -ENFILE }, { nfserr_serverfault, -ENFILE },
{ nfserr_io, -EREMOTEIO }, { nfserr_io, -EREMOTEIO },
{ nfserr_stale, -EOPENSTALE },
{ nfserr_io, -EUCLEAN }, { nfserr_io, -EUCLEAN },
{ nfserr_perm, -ENOKEY }, { nfserr_perm, -ENOKEY },
{ nfserr_no_grace, -ENOGRACE}, { nfserr_no_grace, -ENOGRACE},

View File

@ -777,6 +777,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
int may_flags, struct file **filp) int may_flags, struct file **filp)
{ {
__be32 err; __be32 err;
bool retried = false;
validate_process_creds(); validate_process_creds();
/* /*
@ -792,9 +793,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
*/ */
if (type == S_IFREG) if (type == S_IFREG)
may_flags |= NFSD_MAY_OWNER_OVERRIDE; may_flags |= NFSD_MAY_OWNER_OVERRIDE;
retry:
err = fh_verify(rqstp, fhp, type, may_flags); err = fh_verify(rqstp, fhp, type, may_flags);
if (!err) if (!err) {
err = __nfsd_open(rqstp, fhp, type, may_flags, filp); err = __nfsd_open(rqstp, fhp, type, may_flags, filp);
if (err == nfserr_stale && !retried) {
retried = true;
fh_put(fhp);
goto retry;
}
}
validate_process_creds(); validate_process_creds();
return err; return err;
} }