aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-07-10 23:32:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-07-10 23:32:37 -0400
commit40f06c799539739a08a56be8a096f56aeed05731 (patch)
treeb36fd977d7abaa5041222bd07e600938af28a0d1 /fs/nfs
parenta47f5c56b2eb55290e2a8668e9ca9c029990dbf6 (diff)
parentfe0da9c09b2dc448ff781d1426ecb36d145ce51b (diff)
Merge tag 'copy-file-range-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull copy_file_range updates from Darrick Wong: "This fixes numerous parameter checking problems and inconsistent behaviors in the new(ish) copy_file_range system call. Now the system call will actually check its range parameters correctly; refuse to copy into files for which the caller does not have sufficient privileges; update mtime and strip setuid like file writes are supposed to do; and allows copying up to the EOF of the source file instead of failing the call like we used to. Summary: - Create a generic copy_file_range handler and make individual filesystems responsible for calling it (i.e. no more assuming that do_splice_direct will work or is appropriate) - Refactor copy_file_range and remap_range parameter checking where they are the same - Install missing copy_file_range parameter checking(!) - Remove suid/sgid and update mtime like any other file write - Change the behavior so that a copy range crossing the source file's eof will result in a short copy to the source file's eof instead of EINVAL - Permit filesystems to decide if they want to handle cross-superblock copy_file_range in their local handlers" * tag 'copy-file-range-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: fuse: copy_file_range needs to strip setuid bits and update timestamps vfs: allow copy_file_range to copy across devices xfs: use file_modified() helper vfs: introduce file_modified() helper vfs: add missing checks to copy_file_range vfs: remove redundant checks from generic_remap_checks() vfs: introduce generic_file_rw_checks() vfs: no fallback for ->copy_file_range vfs: introduce generic_copy_file_range()
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4file.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index cf42a8b939e3..f4157eb1f69d 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -129,10 +129,13 @@ nfs4_file_flush(struct file *file, fl_owner_t id)
129} 129}
130 130
131#ifdef CONFIG_NFS_V4_2 131#ifdef CONFIG_NFS_V4_2
132static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, 132static 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 /* Only offload copy if superblock is the same */
137 if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
138 return -EXDEV;
136 if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY)) 139 if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY))
137 return -EOPNOTSUPP; 140 return -EOPNOTSUPP;
138 if (file_inode(file_in) == file_inode(file_out)) 141 if (file_inode(file_in) == file_inode(file_out))
@@ -140,6 +143,20 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
140 return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count); 143 return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
141} 144}
142 145
146static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
147 struct file *file_out, loff_t pos_out,
148 size_t count, unsigned int flags)
149{
150 ssize_t ret;
151
152 ret = __nfs4_copy_file_range(file_in, pos_in, file_out, pos_out, count,
153 flags);
154 if (ret == -EOPNOTSUPP || ret == -EXDEV)
155 ret = generic_copy_file_range(file_in, pos_in, file_out,
156 pos_out, count, flags);
157 return ret;
158}
159
143static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence) 160static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
144{ 161{
145 loff_t ret; 162 loff_t ret;