Skip to content

Commit

Permalink
nfsd: Ensure exclusion between CLONE and WRITE errors
Browse files Browse the repository at this point in the history
Ensure that we can distinguish between synchronous CLONE and
WRITE errors, and that we can assign them correctly.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
  • Loading branch information
trondmy authored and J. Bruce Fields committed Jan 22, 2020
1 parent b66ae6d commit 1b28d75
Showing 1 changed file with 18 additions and 7 deletions.
25 changes: 18 additions & 7 deletions fs/nfsd/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,22 +536,33 @@ __be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
struct file *src = nf_src->nf_file;
struct file *dst = nf_dst->nf_file;
loff_t cloned;
__be32 ret = 0;

down_write(&nf_dst->nf_rwsem);
cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0);
if (cloned < 0)
return nfserrno(cloned);
if (count && cloned != count)
return nfserrno(-EINVAL);
if (cloned < 0) {
ret = nfserrno(cloned);
goto out_err;
}
if (count && cloned != count) {
ret = nfserrno(-EINVAL);
goto out_err;
}
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)
status = commit_inode_metadata(file_inode(src));
if (status < 0)
return nfserrno(status);
if (status < 0) {
nfsd_reset_boot_verifier(net_generic(nf_dst->nf_net,
nfsd_net_id));
ret = nfserrno(status);
}
}
return 0;
out_err:
up_write(&nf_dst->nf_rwsem);
return ret;
}

ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
Expand Down

0 comments on commit 1b28d75

Please sign in to comment.