Commit 5011af4c authored by Trond Myklebust's avatar Trond Myklebust Committed by J. Bruce Fields

nfsd: Fix stable writes

Strictly speaking, a stable write error needs to reflect the
write + the commit of that write (and only that write). To
ensure that we don't pick up the write errors from other
writebacks, add a rw_semaphore to provide exclusion.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 16f8f894
...@@ -195,6 +195,7 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval, ...@@ -195,6 +195,7 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval,
__set_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags); __set_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags);
} }
nf->nf_mark = NULL; nf->nf_mark = NULL;
init_rwsem(&nf->nf_rwsem);
trace_nfsd_file_alloc(nf); trace_nfsd_file_alloc(nf);
} }
return nf; return nf;
......
...@@ -46,6 +46,7 @@ struct nfsd_file { ...@@ -46,6 +46,7 @@ struct nfsd_file {
atomic_t nf_ref; atomic_t nf_ref;
unsigned char nf_may; unsigned char nf_may;
struct nfsd_file_mark *nf_mark; struct nfsd_file_mark *nf_mark;
struct rw_semaphore nf_rwsem;
}; };
int nfsd_file_cache_init(void); int nfsd_file_cache_init(void);
......
...@@ -982,7 +982,18 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, ...@@ -982,7 +982,18 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
flags |= RWF_SYNC; flags |= RWF_SYNC;
iov_iter_kvec(&iter, WRITE, vec, vlen, *cnt); iov_iter_kvec(&iter, WRITE, vec, vlen, *cnt);
if (flags & RWF_SYNC) {
down_write(&nf->nf_rwsem);
host_err = vfs_iter_write(file, &iter, &pos, flags); host_err = vfs_iter_write(file, &iter, &pos, flags);
if (host_err < 0)
nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp),
nfsd_net_id));
up_write(&nf->nf_rwsem);
} else {
down_read(&nf->nf_rwsem);
host_err = vfs_iter_write(file, &iter, &pos, flags);
up_read(&nf->nf_rwsem);
}
if (host_err < 0) if (host_err < 0)
goto out_nfserr; goto out_nfserr;
*cnt = host_err; *cnt = host_err;
...@@ -1097,8 +1108,10 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1097,8 +1108,10 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (err) if (err)
goto out; goto out;
if (EX_ISSYNC(fhp->fh_export)) { if (EX_ISSYNC(fhp->fh_export)) {
int err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); int err2;
down_write(&nf->nf_rwsem);
err2 = vfs_fsync_range(nf->nf_file, offset, end, 0);
switch (err2) { switch (err2) {
case 0: case 0:
break; break;
...@@ -1110,6 +1123,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1110,6 +1123,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
nfsd_reset_boot_verifier(net_generic(nf->nf_net, nfsd_reset_boot_verifier(net_generic(nf->nf_net,
nfsd_net_id)); nfsd_net_id));
} }
up_write(&nf->nf_rwsem);
} }
nfsd_file_put(nf); nfsd_file_put(nf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment