nfsd: Don't reset the write verifier on a commit EAGAIN
If fsync() is returning EAGAIN, then we can assume that the filesystem being exported is something like NFS with the 'softerr' mount option enabled, and that it is just asking us to replay the fsync() operation at a later date. If we see an ESTALE, then ditto: the file is gone, so there is no danger of losing the error. For those cases, do not reset the write verifier. A write verifier change has a global effect, causing retransmission by all clients of all uncommitted unstable writes for all files, so it is worth mitigating where possible. Link: https://lore.kernel.org/linux-nfs/20230911184357.11739-1-trond.myklebust@hammerspace.com/ Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
d59b3515ab
commit
1b2021bdee
@ -337,6 +337,24 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
commit_reset_write_verifier(struct nfsd_net *nn, struct svc_rqst *rqstp,
|
||||
int err)
|
||||
{
|
||||
switch (err) {
|
||||
case -EAGAIN:
|
||||
case -ESTALE:
|
||||
/*
|
||||
* Neither of these are the result of a problem with
|
||||
* durable storage, so avoid a write verifier reset.
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
nfsd_reset_write_verifier(nn);
|
||||
trace_nfsd_writeverf_reset(nn, rqstp, err);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Commit metadata changes to stable storage.
|
||||
*/
|
||||
@ -647,8 +665,7 @@ __be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
|
||||
&nfsd4_get_cstate(rqstp)->current_fh,
|
||||
dst_pos,
|
||||
count, status);
|
||||
nfsd_reset_write_verifier(nn);
|
||||
trace_nfsd_writeverf_reset(nn, rqstp, status);
|
||||
commit_reset_write_verifier(nn, rqstp, status);
|
||||
ret = nfserrno(status);
|
||||
}
|
||||
}
|
||||
@ -1170,8 +1187,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
|
||||
host_err = vfs_iter_write(file, &iter, &pos, flags);
|
||||
file_end_write(file);
|
||||
if (host_err < 0) {
|
||||
nfsd_reset_write_verifier(nn);
|
||||
trace_nfsd_writeverf_reset(nn, rqstp, host_err);
|
||||
commit_reset_write_verifier(nn, rqstp, host_err);
|
||||
goto out_nfserr;
|
||||
}
|
||||
*cnt = host_err;
|
||||
@ -1183,10 +1199,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
|
||||
|
||||
if (stable && use_wgather) {
|
||||
host_err = wait_for_concurrent_writes(file);
|
||||
if (host_err < 0) {
|
||||
nfsd_reset_write_verifier(nn);
|
||||
trace_nfsd_writeverf_reset(nn, rqstp, host_err);
|
||||
}
|
||||
if (host_err < 0)
|
||||
commit_reset_write_verifier(nn, rqstp, host_err);
|
||||
}
|
||||
|
||||
out_nfserr:
|
||||
@ -1329,8 +1343,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
|
||||
err = nfserr_notsupp;
|
||||
break;
|
||||
default:
|
||||
nfsd_reset_write_verifier(nn);
|
||||
trace_nfsd_writeverf_reset(nn, rqstp, err2);
|
||||
commit_reset_write_verifier(nn, rqstp, err2);
|
||||
err = nfserrno(err2);
|
||||
}
|
||||
} else
|
||||
|
Loading…
x
Reference in New Issue
Block a user