aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-10-29 19:41:49 -0400
committerDave Chinner <david@fromorbit.com>2018-10-29 19:41:49 -0400
commit42ec3d4c02187a18e27ff94b409ec27234bf2ffd (patch)
treec9db04db8187c370718a43e6067af0e5aa944500
parent8dde90bca6fca3736ea20109654bcf6dcf2ecf1d (diff)
vfs: make remap_file_range functions take and return bytes completed
Change the remap_file_range functions to take a number of bytes to operate upon and return the number of bytes they operated on. This is a requirement for allowing fs implementations to return short clone/dedupe results to the user, which will enable us to obey resource limits in a graceful manner. A subsequent patch will enable copy_file_range to signal to the ->clone_file_range implementation that it can handle a short length, which will be returned in the function's return value. For now the short return is not implemented anywhere so the behavior won't change -- either copy_file_range manages to clone the entire range or it tries an alternative. Neither clone ioctl can take advantage of this, alas. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--Documentation/filesystems/vfs.txt10
-rw-r--r--fs/btrfs/ctree.h6
-rw-r--r--fs/btrfs/ioctl.c13
-rw-r--r--fs/cifs/cifsfs.c6
-rw-r--r--fs/ioctl.c10
-rw-r--r--fs/nfs/nfs4file.c6
-rw-r--r--fs/nfsd/vfs.c8
-rw-r--r--fs/ocfs2/file.c16
-rw-r--r--fs/ocfs2/refcounttree.c2
-rw-r--r--fs/ocfs2/refcounttree.h2
-rw-r--r--fs/overlayfs/copy_up.c6
-rw-r--r--fs/overlayfs/file.c12
-rw-r--r--fs/read_write.c49
-rw-r--r--fs/xfs/xfs_file.c9
-rw-r--r--fs/xfs/xfs_reflink.c4
-rw-r--r--fs/xfs/xfs_reflink.h2
-rw-r--r--include/linux/fs.h27
-rw-r--r--mm/filemap.c2
18 files changed, 108 insertions, 82 deletions
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 6f5babfee27b..1bd2919deaca 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -883,9 +883,9 @@ struct file_operations {
883 unsigned (*mmap_capabilities)(struct file *); 883 unsigned (*mmap_capabilities)(struct file *);
884#endif 884#endif
885 ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int); 885 ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int);
886 int (*remap_file_range)(struct file *file_in, loff_t pos_in, 886 loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
887 struct file *file_out, loff_t pos_out, 887 struct file *file_out, loff_t pos_out,
888 u64 len, unsigned int remap_flags); 888 loff_t len, unsigned int remap_flags);
889 int (*fadvise)(struct file *, loff_t, loff_t, int); 889 int (*fadvise)(struct file *, loff_t, loff_t, int);
890}; 890};
891 891
@@ -966,8 +966,8 @@ otherwise noted.
966 implementation should remap len bytes at pos_in of the source file into 966 implementation should remap len bytes at pos_in of the source file into
967 the dest file at pos_out. Implementations must handle callers passing 967 the dest file at pos_out. Implementations must handle callers passing
968 in len == 0; this means "remap to the end of the source file". The 968 in len == 0; this means "remap to the end of the source file". The
969 return value should be zero if all bytes were remapped, or the usual 969 return value should the number of bytes remapped, or the usual
970 negative error code if the remapping did not succeed completely. 970 negative error code if errors occurred before any bytes were remapped.
971 The remap_flags parameter accepts REMAP_FILE_* flags. If 971 The remap_flags parameter accepts REMAP_FILE_* flags. If
972 REMAP_FILE_DEDUP is set then the implementation must only remap if the 972 REMAP_FILE_DEDUP is set then the implementation must only remap if the
973 requested file ranges have identical contents. 973 requested file ranges have identical contents.
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 124a05662fc2..771a961d77ad 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3247,9 +3247,9 @@ int btrfs_dirty_pages(struct inode *inode, struct page **pages,
3247 size_t num_pages, loff_t pos, size_t write_bytes, 3247 size_t num_pages, loff_t pos, size_t write_bytes,
3248 struct extent_state **cached); 3248 struct extent_state **cached);
3249int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end); 3249int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end);
3250int btrfs_remap_file_range(struct file *file_in, loff_t pos_in, 3250loff_t btrfs_remap_file_range(struct file *file_in, loff_t pos_in,
3251 struct file *file_out, loff_t pos_out, u64 len, 3251 struct file *file_out, loff_t pos_out,
3252 unsigned int remap_flags); 3252 loff_t len, unsigned int remap_flags);
3253 3253
3254/* tree-defrag.c */ 3254/* tree-defrag.c */
3255int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, 3255int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index bfd99c66723e..b0c513e10977 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4328,10 +4328,12 @@ out_unlock:
4328 return ret; 4328 return ret;
4329} 4329}
4330 4330
4331int btrfs_remap_file_range(struct file *src_file, loff_t off, 4331loff_t btrfs_remap_file_range(struct file *src_file, loff_t off,
4332 struct file *dst_file, loff_t destoff, u64 len, 4332 struct file *dst_file, loff_t destoff, loff_t len,
4333 unsigned int remap_flags) 4333 unsigned int remap_flags)
4334{ 4334{
4335 int ret;
4336
4335 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) 4337 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
4336 return -EINVAL; 4338 return -EINVAL;
4337 4339
@@ -4349,10 +4351,11 @@ int btrfs_remap_file_range(struct file *src_file, loff_t off,
4349 return -EINVAL; 4351 return -EINVAL;
4350 } 4352 }
4351 4353
4352 return btrfs_extent_same(src, off, len, dst, destoff); 4354 ret = btrfs_extent_same(src, off, len, dst, destoff);
4355 } else {
4356 ret = btrfs_clone_files(dst_file, src_file, off, len, destoff);
4353 } 4357 }
4354 4358 return ret < 0 ? ret : len;
4355 return btrfs_clone_files(dst_file, src_file, off, len, destoff);
4356} 4359}
4357 4360
4358static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) 4361static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e8144d0dcde2..5ca71c6c8be2 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -975,8 +975,8 @@ const struct inode_operations cifs_symlink_inode_ops = {
975 .listxattr = cifs_listxattr, 975 .listxattr = cifs_listxattr,
976}; 976};
977 977
978static int cifs_remap_file_range(struct file *src_file, loff_t off, 978static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
979 struct file *dst_file, loff_t destoff, u64 len, 979 struct file *dst_file, loff_t destoff, loff_t len,
980 unsigned int remap_flags) 980 unsigned int remap_flags)
981{ 981{
982 struct inode *src_inode = file_inode(src_file); 982 struct inode *src_inode = file_inode(src_file);
@@ -1029,7 +1029,7 @@ static int cifs_remap_file_range(struct file *src_file, loff_t off,
1029 unlock_two_nondirectories(src_inode, target_inode); 1029 unlock_two_nondirectories(src_inode, target_inode);
1030out: 1030out:
1031 free_xid(xid); 1031 free_xid(xid);
1032 return rc; 1032 return rc < 0 ? rc : len;
1033} 1033}
1034 1034
1035ssize_t cifs_file_copychunk_range(unsigned int xid, 1035ssize_t cifs_file_copychunk_range(unsigned int xid,
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 2005529af560..72537b68c272 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -223,6 +223,7 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
223 u64 off, u64 olen, u64 destoff) 223 u64 off, u64 olen, u64 destoff)
224{ 224{
225 struct fd src_file = fdget(srcfd); 225 struct fd src_file = fdget(srcfd);
226 loff_t cloned;
226 int ret; 227 int ret;
227 228
228 if (!src_file.file) 229 if (!src_file.file)
@@ -230,7 +231,14 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
230 ret = -EXDEV; 231 ret = -EXDEV;
231 if (src_file.file->f_path.mnt != dst_file->f_path.mnt) 232 if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
232 goto fdput; 233 goto fdput;
233 ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen); 234 cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff,
235 olen);
236 if (cloned < 0)
237 ret = cloned;
238 else if (olen && cloned != olen)
239 ret = -EINVAL;
240 else
241 ret = 0;
234fdput: 242fdput:
235 fdput(src_file); 243 fdput(src_file);
236 return ret; 244 return ret;
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index ae5780ce41dc..46d691ba04bc 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -180,8 +180,8 @@ static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t
180 return nfs42_proc_allocate(filep, offset, len); 180 return nfs42_proc_allocate(filep, offset, len);
181} 181}
182 182
183static int nfs42_remap_file_range(struct file *src_file, loff_t src_off, 183static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
184 struct file *dst_file, loff_t dst_off, u64 count, 184 struct file *dst_file, loff_t dst_off, loff_t count,
185 unsigned int remap_flags) 185 unsigned int remap_flags)
186{ 186{
187 struct inode *dst_inode = file_inode(dst_file); 187 struct inode *dst_inode = file_inode(dst_file);
@@ -244,7 +244,7 @@ out_unlock:
244 inode_unlock(src_inode); 244 inode_unlock(src_inode);
245 } 245 }
246out: 246out:
247 return ret; 247 return ret < 0 ? ret : count;
248} 248}
249#endif /* CONFIG_NFS_V4_2 */ 249#endif /* CONFIG_NFS_V4_2 */
250 250
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index b53e76391e52..ac6cb6101cbe 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -541,8 +541,12 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
541__be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, 541__be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
542 u64 dst_pos, u64 count) 542 u64 dst_pos, u64 count)
543{ 543{
544 return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos, 544 loff_t cloned;
545 count)); 545
546 cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count);
547 if (count && cloned != count)
548 cloned = -EINVAL;
549 return nfserrno(cloned < 0 ? cloned : 0);
546} 550}
547 551
548ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst, 552ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 9809b0e5746f..fbaeafe44b5f 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2527,18 +2527,18 @@ out:
2527 return offset; 2527 return offset;
2528} 2528}
2529 2529
2530static int ocfs2_remap_file_range(struct file *file_in, 2530static loff_t ocfs2_remap_file_range(struct file *file_in, loff_t pos_in,
2531 loff_t pos_in, 2531 struct file *file_out, loff_t pos_out,
2532 struct file *file_out, 2532 loff_t len, unsigned int remap_flags)
2533 loff_t pos_out,
2534 u64 len,
2535 unsigned int remap_flags)
2536{ 2533{
2534 int ret;
2535
2537 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) 2536 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
2538 return -EINVAL; 2537 return -EINVAL;
2539 2538
2540 return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, 2539 ret = ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out,
2541 len, remap_flags); 2540 len, remap_flags);
2541 return ret < 0 ? ret : len;
2542} 2542}
2543 2543
2544const struct inode_operations ocfs2_file_iops = { 2544const struct inode_operations ocfs2_file_iops = {
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index df9781567ec0..6a42c04ac0ab 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -4824,7 +4824,7 @@ int ocfs2_reflink_remap_range(struct file *file_in,
4824 loff_t pos_in, 4824 loff_t pos_in,
4825 struct file *file_out, 4825 struct file *file_out,
4826 loff_t pos_out, 4826 loff_t pos_out,
4827 u64 len, 4827 loff_t len,
4828 unsigned int remap_flags) 4828 unsigned int remap_flags)
4829{ 4829{
4830 struct inode *inode_in = file_inode(file_in); 4830 struct inode *inode_in = file_inode(file_in);
diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h
index d2c5f526edff..eb65c1d0843c 100644
--- a/fs/ocfs2/refcounttree.h
+++ b/fs/ocfs2/refcounttree.h
@@ -119,7 +119,7 @@ int ocfs2_reflink_remap_range(struct file *file_in,
119 loff_t pos_in, 119 loff_t pos_in,
120 struct file *file_out, 120 struct file *file_out,
121 loff_t pos_out, 121 loff_t pos_out,
122 u64 len, 122 loff_t len,
123 unsigned int remap_flags); 123 unsigned int remap_flags);
124 124
125#endif /* OCFS2_REFCOUNTTREE_H */ 125#endif /* OCFS2_REFCOUNTTREE_H */
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 1cc797a08a5b..8750b7235516 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -125,6 +125,7 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
125 struct file *new_file; 125 struct file *new_file;
126 loff_t old_pos = 0; 126 loff_t old_pos = 0;
127 loff_t new_pos = 0; 127 loff_t new_pos = 0;
128 loff_t cloned;
128 int error = 0; 129 int error = 0;
129 130
130 if (len == 0) 131 if (len == 0)
@@ -141,11 +142,10 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
141 } 142 }
142 143
143 /* Try to use clone_file_range to clone up within the same fs */ 144 /* Try to use clone_file_range to clone up within the same fs */
144 error = do_clone_file_range(old_file, 0, new_file, 0, len); 145 cloned = do_clone_file_range(old_file, 0, new_file, 0, len);
145 if (!error) 146 if (cloned == len)
146 goto out; 147 goto out;
147 /* Couldn't clone, so now we try to copy the data */ 148 /* Couldn't clone, so now we try to copy the data */
148 error = 0;
149 149
150 /* FIXME: copy up sparse files efficiently */ 150 /* FIXME: copy up sparse files efficiently */
151 while (len) { 151 while (len) {
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index fffb36fd5920..6c3fec6168e9 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -434,14 +434,14 @@ enum ovl_copyop {
434 OVL_DEDUPE, 434 OVL_DEDUPE,
435}; 435};
436 436
437static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, 437static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
438 struct file *file_out, loff_t pos_out, 438 struct file *file_out, loff_t pos_out,
439 u64 len, unsigned int flags, enum ovl_copyop op) 439 loff_t len, unsigned int flags, enum ovl_copyop op)
440{ 440{
441 struct inode *inode_out = file_inode(file_out); 441 struct inode *inode_out = file_inode(file_out);
442 struct fd real_in, real_out; 442 struct fd real_in, real_out;
443 const struct cred *old_cred; 443 const struct cred *old_cred;
444 ssize_t ret; 444 loff_t ret;
445 445
446 ret = ovl_real_fdget(file_out, &real_out); 446 ret = ovl_real_fdget(file_out, &real_out);
447 if (ret) 447 if (ret)
@@ -489,9 +489,9 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in,
489 OVL_COPY); 489 OVL_COPY);
490} 490}
491 491
492static int ovl_remap_file_range(struct file *file_in, loff_t pos_in, 492static loff_t ovl_remap_file_range(struct file *file_in, loff_t pos_in,
493 struct file *file_out, loff_t pos_out, 493 struct file *file_out, loff_t pos_out,
494 u64 len, unsigned int remap_flags) 494 loff_t len, unsigned int remap_flags)
495{ 495{
496 enum ovl_copyop op; 496 enum ovl_copyop op;
497 497
diff --git a/fs/read_write.c b/fs/read_write.c
index b61bd3fc7154..356641afa487 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1589,10 +1589,13 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
1589 * more efficient if both clone and copy are supported (e.g. NFS). 1589 * more efficient if both clone and copy are supported (e.g. NFS).
1590 */ 1590 */
1591 if (file_in->f_op->remap_file_range) { 1591 if (file_in->f_op->remap_file_range) {
1592 ret = file_in->f_op->remap_file_range(file_in, pos_in, 1592 loff_t cloned;
1593 file_out, pos_out, len, 0); 1593
1594 if (ret == 0) { 1594 cloned = file_in->f_op->remap_file_range(file_in, pos_in,
1595 ret = len; 1595 file_out, pos_out,
1596 min_t(loff_t, MAX_RW_COUNT, len), 0);
1597 if (cloned > 0) {
1598 ret = cloned;
1596 goto done; 1599 goto done;
1597 } 1600 }
1598 } 1601 }
@@ -1686,11 +1689,12 @@ out2:
1686 return ret; 1689 return ret;
1687} 1690}
1688 1691
1689static int remap_verify_area(struct file *file, loff_t pos, u64 len, bool write) 1692static int remap_verify_area(struct file *file, loff_t pos, loff_t len,
1693 bool write)
1690{ 1694{
1691 struct inode *inode = file_inode(file); 1695 struct inode *inode = file_inode(file);
1692 1696
1693 if (unlikely(pos < 0)) 1697 if (unlikely(pos < 0 || len < 0))
1694 return -EINVAL; 1698 return -EINVAL;
1695 1699
1696 if (unlikely((loff_t) (pos + len) < 0)) 1700 if (unlikely((loff_t) (pos + len) < 0))
@@ -1721,7 +1725,7 @@ static int remap_verify_area(struct file *file, loff_t pos, u64 len, bool write)
1721static int generic_remap_check_len(struct inode *inode_in, 1725static int generic_remap_check_len(struct inode *inode_in,
1722 struct inode *inode_out, 1726 struct inode *inode_out,
1723 loff_t pos_out, 1727 loff_t pos_out,
1724 u64 *len, 1728 loff_t *len,
1725 unsigned int remap_flags) 1729 unsigned int remap_flags)
1726{ 1730{
1727 u64 blkmask = i_blocksize(inode_in) - 1; 1731 u64 blkmask = i_blocksize(inode_in) - 1;
@@ -1747,7 +1751,7 @@ static int generic_remap_check_len(struct inode *inode_in,
1747 */ 1751 */
1748int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, 1752int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
1749 struct file *file_out, loff_t pos_out, 1753 struct file *file_out, loff_t pos_out,
1750 u64 *len, unsigned int remap_flags) 1754 loff_t *len, unsigned int remap_flags)
1751{ 1755{
1752 struct inode *inode_in = file_inode(file_in); 1756 struct inode *inode_in = file_inode(file_in);
1753 struct inode *inode_out = file_inode(file_out); 1757 struct inode *inode_out = file_inode(file_out);
@@ -1843,12 +1847,12 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
1843} 1847}
1844EXPORT_SYMBOL(generic_remap_file_range_prep); 1848EXPORT_SYMBOL(generic_remap_file_range_prep);
1845 1849
1846int do_clone_file_range(struct file *file_in, loff_t pos_in, 1850loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
1847 struct file *file_out, loff_t pos_out, u64 len) 1851 struct file *file_out, loff_t pos_out, loff_t len)
1848{ 1852{
1849 struct inode *inode_in = file_inode(file_in); 1853 struct inode *inode_in = file_inode(file_in);
1850 struct inode *inode_out = file_inode(file_out); 1854 struct inode *inode_out = file_inode(file_out);
1851 int ret; 1855 loff_t ret;
1852 1856
1853 if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) 1857 if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
1854 return -EISDIR; 1858 return -EISDIR;
@@ -1881,19 +1885,19 @@ int do_clone_file_range(struct file *file_in, loff_t pos_in,
1881 1885
1882 ret = file_in->f_op->remap_file_range(file_in, pos_in, 1886 ret = file_in->f_op->remap_file_range(file_in, pos_in,
1883 file_out, pos_out, len, 0); 1887 file_out, pos_out, len, 0);
1884 if (!ret) { 1888 if (ret < 0)
1885 fsnotify_access(file_in); 1889 return ret;
1886 fsnotify_modify(file_out);
1887 }
1888 1890
1891 fsnotify_access(file_in);
1892 fsnotify_modify(file_out);
1889 return ret; 1893 return ret;
1890} 1894}
1891EXPORT_SYMBOL(do_clone_file_range); 1895EXPORT_SYMBOL(do_clone_file_range);
1892 1896
1893int vfs_clone_file_range(struct file *file_in, loff_t pos_in, 1897loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
1894 struct file *file_out, loff_t pos_out, u64 len) 1898 struct file *file_out, loff_t pos_out, loff_t len)
1895{ 1899{
1896 int ret; 1900 loff_t ret;
1897 1901
1898 file_start_write(file_out); 1902 file_start_write(file_out);
1899 ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len); 1903 ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len);
@@ -1999,10 +2003,11 @@ out_error:
1999} 2003}
2000EXPORT_SYMBOL(vfs_dedupe_file_range_compare); 2004EXPORT_SYMBOL(vfs_dedupe_file_range_compare);
2001 2005
2002int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, 2006loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
2003 struct file *dst_file, loff_t dst_pos, u64 len) 2007 struct file *dst_file, loff_t dst_pos,
2008 loff_t len)
2004{ 2009{
2005 s64 ret; 2010 loff_t ret;
2006 2011
2007 ret = mnt_want_write_file(dst_file); 2012 ret = mnt_want_write_file(dst_file);
2008 if (ret) 2013 if (ret)
@@ -2051,7 +2056,7 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
2051 int i; 2056 int i;
2052 int ret; 2057 int ret;
2053 u16 count = same->dest_count; 2058 u16 count = same->dest_count;
2054 int deduped; 2059 loff_t deduped;
2055 2060
2056 if (!(file->f_mode & FMODE_READ)) 2061 if (!(file->f_mode & FMODE_READ))
2057 return -EINVAL; 2062 return -EINVAL;
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 20314eb4677a..38fde4e11714 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -919,20 +919,23 @@ out_unlock:
919 return error; 919 return error;
920} 920}
921 921
922STATIC int 922STATIC loff_t
923xfs_file_remap_range( 923xfs_file_remap_range(
924 struct file *file_in, 924 struct file *file_in,
925 loff_t pos_in, 925 loff_t pos_in,
926 struct file *file_out, 926 struct file *file_out,
927 loff_t pos_out, 927 loff_t pos_out,
928 u64 len, 928 loff_t len,
929 unsigned int remap_flags) 929 unsigned int remap_flags)
930{ 930{
931 int ret;
932
931 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) 933 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
932 return -EINVAL; 934 return -EINVAL;
933 935
934 return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out, 936 ret = xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out,
935 len, remap_flags); 937 len, remap_flags);
938 return ret < 0 ? ret : len;
936} 939}
937 940
938STATIC int 941STATIC int
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 2d7dd8b28d7c..3dbe5fb7e9c0 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1296,7 +1296,7 @@ xfs_reflink_remap_prep(
1296 loff_t pos_in, 1296 loff_t pos_in,
1297 struct file *file_out, 1297 struct file *file_out,
1298 loff_t pos_out, 1298 loff_t pos_out,
1299 u64 *len, 1299 loff_t *len,
1300 unsigned int remap_flags) 1300 unsigned int remap_flags)
1301{ 1301{
1302 struct inode *inode_in = file_inode(file_in); 1302 struct inode *inode_in = file_inode(file_in);
@@ -1387,7 +1387,7 @@ xfs_reflink_remap_range(
1387 loff_t pos_in, 1387 loff_t pos_in,
1388 struct file *file_out, 1388 struct file *file_out,
1389 loff_t pos_out, 1389 loff_t pos_out,
1390 u64 len, 1390 loff_t len,
1391 unsigned int remap_flags) 1391 unsigned int remap_flags)
1392{ 1392{
1393 struct inode *inode_in = file_inode(file_in); 1393 struct inode *inode_in = file_inode(file_in);
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index 6f82d628bf17..c3c46c276fe1 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -28,7 +28,7 @@ extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset,
28 xfs_off_t count); 28 xfs_off_t count);
29extern int xfs_reflink_recover_cow(struct xfs_mount *mp); 29extern int xfs_reflink_recover_cow(struct xfs_mount *mp);
30extern int xfs_reflink_remap_range(struct file *file_in, loff_t pos_in, 30extern int xfs_reflink_remap_range(struct file *file_in, loff_t pos_in,
31 struct file *file_out, loff_t pos_out, u64 len, 31 struct file *file_out, loff_t pos_out, loff_t len,
32 unsigned int remap_flags); 32 unsigned int remap_flags);
33extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp, 33extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp,
34 struct xfs_inode *ip, bool *has_shared); 34 struct xfs_inode *ip, bool *has_shared);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c5435ca81132..c72d8c3c065a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1777,9 +1777,9 @@ struct file_operations {
1777#endif 1777#endif
1778 ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, 1778 ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
1779 loff_t, size_t, unsigned int); 1779 loff_t, size_t, unsigned int);
1780 int (*remap_file_range)(struct file *file_in, loff_t pos_in, 1780 loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
1781 struct file *file_out, loff_t pos_out, 1781 struct file *file_out, loff_t pos_out,
1782 u64 len, unsigned int remap_flags); 1782 loff_t len, unsigned int remap_flags);
1783 int (*fadvise)(struct file *, loff_t, loff_t, int); 1783 int (*fadvise)(struct file *, loff_t, loff_t, int);
1784} __randomize_layout; 1784} __randomize_layout;
1785 1785
@@ -1844,19 +1844,22 @@ extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *,
1844 loff_t, size_t, unsigned int); 1844 loff_t, size_t, unsigned int);
1845extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, 1845extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
1846 struct file *file_out, loff_t pos_out, 1846 struct file *file_out, loff_t pos_out,
1847 u64 *count, unsigned int remap_flags); 1847 loff_t *count,
1848extern int do_clone_file_range(struct file *file_in, loff_t pos_in, 1848 unsigned int remap_flags);
1849 struct file *file_out, loff_t pos_out, u64 len); 1849extern loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
1850extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in, 1850 struct file *file_out, loff_t pos_out,
1851 struct file *file_out, loff_t pos_out, u64 len); 1851 loff_t len);
1852extern loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
1853 struct file *file_out, loff_t pos_out,
1854 loff_t len);
1852extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, 1855extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
1853 struct inode *dest, loff_t destoff, 1856 struct inode *dest, loff_t destoff,
1854 loff_t len, bool *is_same); 1857 loff_t len, bool *is_same);
1855extern int vfs_dedupe_file_range(struct file *file, 1858extern int vfs_dedupe_file_range(struct file *file,
1856 struct file_dedupe_range *same); 1859 struct file_dedupe_range *same);
1857extern int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, 1860extern loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
1858 struct file *dst_file, loff_t dst_pos, 1861 struct file *dst_file, loff_t dst_pos,
1859 u64 len); 1862 loff_t len);
1860 1863
1861 1864
1862struct super_operations { 1865struct super_operations {
@@ -2986,7 +2989,7 @@ extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
2986extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *); 2989extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *);
2987extern int generic_remap_checks(struct file *file_in, loff_t pos_in, 2990extern int generic_remap_checks(struct file *file_in, loff_t pos_in,
2988 struct file *file_out, loff_t pos_out, 2991 struct file *file_out, loff_t pos_out,
2989 uint64_t *count, unsigned int remap_flags); 2992 loff_t *count, unsigned int remap_flags);
2990extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); 2993extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *);
2991extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); 2994extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *);
2992extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); 2995extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *);
diff --git a/mm/filemap.c b/mm/filemap.c
index 410dc58f7b16..e9091d731f84 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2994,7 +2994,7 @@ EXPORT_SYMBOL(generic_write_checks);
2994 */ 2994 */
2995int generic_remap_checks(struct file *file_in, loff_t pos_in, 2995int generic_remap_checks(struct file *file_in, loff_t pos_in,
2996 struct file *file_out, loff_t pos_out, 2996 struct file *file_out, loff_t pos_out,
2997 uint64_t *req_count, unsigned int remap_flags) 2997 loff_t *req_count, unsigned int remap_flags)
2998{ 2998{
2999 struct inode *inode_in = file_in->f_mapping->host; 2999 struct inode *inode_in = file_in->f_mapping->host;
3000 struct inode *inode_out = file_out->f_mapping->host; 3000 struct inode *inode_out = file_out->f_mapping->host;