From: Trond Myklebust trondmy@gmail.com
mainline inclusion from mainline-v5.5-rc1 commit a25e3726b32c746c0098125d4c7463bb84df72bb category: bugfix bugzilla: 27346 CVE: NA
-------------------------------------------------
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: ffa0160a1039 ("nfsd: implement the NFSv4.2 CLONE operation") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Cc: stable@vger.kernel.org # v4.5+ Signed-off-by: J. Bruce Fields bfields@redhat.com
Conflicts: fs/nfsd/nfs4proc.c fs/nfsd/vfs.c 42ec3d4c0218 ("vfs: make remap_file_range functions take and return bytes completed") 2e5dfc99f2e6 ("vfs: combine the clone and dedupe into a single remap_file_range")
Signed-off-by: Zhang Xiaoxu zhangxiaoxu5@huawei.com Reviewed-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/nfsd/nfs4proc.c | 3 ++- fs/nfsd/vfs.c | 16 +++++++++++++--- fs/nfsd/vfs.h | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index f35aa9f88b5ec..1c3e6de6bcba9 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1082,7 +1082,8 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out;
status = nfsd4_clone_file_range(src, clone->cl_src_pos, - dst, clone->cl_dst_pos, clone->cl_count); + dst, clone->cl_dst_pos, clone->cl_count, + EX_ISSYNC(cstate->current_fh.fh_export));
fput(dst); fput(src); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f79bcb1f198b7..404e8846cc7c1 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -552,10 +552,20 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, #endif
__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) { - return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos, - count)); + int cloned; + + cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count); + if (cloned < 0) + return nfserrno(cloned); + 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; }
ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst, diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index db351247892d0..02b0a140af8cc 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h @@ -58,7 +58,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *, struct file *, loff_t, loff_t, int); __be32 nfsd4_clone_file_range(struct file *, u64, struct file *, - u64, u64); + u64, u64, bool); #endif /* CONFIG_NFSD_V4 */ __be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs,