diff options
| author | Olga Kornievskaia <kolga@netapp.com> | 2019-04-11 14:34:18 -0400 |
|---|---|---|
| committer | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-04-11 15:23:48 -0400 |
| commit | 0769663b4f580566ef6cdf366f3073dbe8022c39 (patch) | |
| tree | 96eb99500c11d736c336f960b3e12bbdeb132e51 | |
| parent | e1ede312f17e96a9c5cda9aaa1cdcf442c1a5da8 (diff) | |
NFSv4.1 fix incorrect return value in copy_file_range
According to the NFSv4.2 spec if the input and output file is the
same file, operation should fail with EINVAL. However, linux
copy_file_range() system call has no such restrictions. Therefore,
in such case let's return EOPNOTSUPP and allow VFS to fallback
to doing do_splice_direct(). Also when copy_file_range is called
on an NFSv4.0 or 4.1 mount (ie., a server that doesn't support
COPY functionality), we also need to return EOPNOTSUPP and
fallback to a regular copy.
Fixes xfstest generic/075, generic/091, generic/112, generic/263
for all NFSv4.x versions.
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
| -rw-r--r-- | fs/nfs/nfs42proc.c | 3 | ||||
| -rw-r--r-- | fs/nfs/nfs4file.c | 4 |
2 files changed, 3 insertions, 4 deletions
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index ff6f85fb676b..5196bfa7894d 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
| @@ -329,9 +329,6 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src, | |||
| 329 | }; | 329 | }; |
| 330 | ssize_t err, err2; | 330 | ssize_t err, err2; |
| 331 | 331 | ||
| 332 | if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY)) | ||
| 333 | return -EOPNOTSUPP; | ||
| 334 | |||
| 335 | src_lock = nfs_get_lock_context(nfs_file_open_context(src)); | 332 | src_lock = nfs_get_lock_context(nfs_file_open_context(src)); |
| 336 | if (IS_ERR(src_lock)) | 333 | if (IS_ERR(src_lock)) |
| 337 | return PTR_ERR(src_lock); | 334 | return PTR_ERR(src_lock); |
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 45b2322e092d..00d17198ee12 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
| @@ -133,8 +133,10 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, | |||
| 133 | struct file *file_out, loff_t pos_out, | 133 | struct file *file_out, loff_t pos_out, |
| 134 | size_t count, unsigned int flags) | 134 | size_t count, unsigned int flags) |
| 135 | { | 135 | { |
| 136 | if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY)) | ||
| 137 | return -EOPNOTSUPP; | ||
| 136 | if (file_inode(file_in) == file_inode(file_out)) | 138 | if (file_inode(file_in) == file_inode(file_out)) |
| 137 | return -EINVAL; | 139 | return -EOPNOTSUPP; |
| 138 | return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count); | 140 | return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count); |
| 139 | } | 141 | } |
| 140 | 142 | ||
