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

nfsd: Ensure CLONE persists data and metadata changes to the target file

The NFSv4.2 CLONE operation has implicit persistence requirements on the
target file, since there is no protocol requirement that the client issue
a separate operation to persist data.
For that reason, we should call vfs_fsync_range() on the destination file
after a successful call to vfs_clone_file_range().

Fixes: ffa0160a ("nfsd: implement the NFSv4.2 CLONE operation")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Cc: stable@vger.kernel.org # v4.5+
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 8729aaba
...@@ -1077,7 +1077,8 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -1077,7 +1077,8 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
goto out; goto out;
status = nfsd4_clone_file_range(src->nf_file, clone->cl_src_pos, status = nfsd4_clone_file_range(src->nf_file, clone->cl_src_pos,
dst->nf_file, clone->cl_dst_pos, clone->cl_count); dst->nf_file, clone->cl_dst_pos, clone->cl_count,
EX_ISSYNC(cstate->current_fh.fh_export));
nfsd_file_put(dst); nfsd_file_put(dst);
nfsd_file_put(src); nfsd_file_put(src);
......
...@@ -525,7 +525,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -525,7 +525,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
#endif #endif
__be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
u64 dst_pos, u64 count) u64 dst_pos, u64 count, bool sync)
{ {
loff_t cloned; loff_t cloned;
...@@ -534,6 +534,12 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, ...@@ -534,6 +534,12 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
return nfserrno(cloned); return nfserrno(cloned);
if (count && cloned != count) if (count && cloned != count)
return nfserrno(-EINVAL); return nfserrno(-EINVAL);
if (sync) {
loff_t dst_end = count ? dst_pos + count - 1 : LLONG_MAX;
int status = vfs_fsync_range(dst, dst_pos, dst_end, 0);
if (status < 0)
return nfserrno(status);
}
return 0; return 0;
} }
......
...@@ -56,7 +56,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, ...@@ -56,7 +56,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
__be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *, __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
struct file *, loff_t, loff_t, int); struct file *, loff_t, loff_t, int);
__be32 nfsd4_clone_file_range(struct file *, u64, struct file *, __be32 nfsd4_clone_file_range(struct file *, u64, struct file *,
u64, u64); u64, u64, bool);
#endif /* CONFIG_NFSD_V4 */ #endif /* CONFIG_NFSD_V4 */
__be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *, __be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs, char *name, int len, struct iattr *attrs,
......
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