Commit 42ec3d4c authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Dave Chinner

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: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 8dde90bc
...@@ -883,9 +883,9 @@ struct file_operations { ...@@ -883,9 +883,9 @@ struct file_operations {
unsigned (*mmap_capabilities)(struct file *); unsigned (*mmap_capabilities)(struct file *);
#endif #endif
ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int); ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int);
int (*remap_file_range)(struct file *file_in, loff_t pos_in, loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
u64 len, unsigned int remap_flags); loff_t len, unsigned int remap_flags);
int (*fadvise)(struct file *, loff_t, loff_t, int); int (*fadvise)(struct file *, loff_t, loff_t, int);
}; };
...@@ -966,8 +966,8 @@ otherwise noted. ...@@ -966,8 +966,8 @@ otherwise noted.
implementation should remap len bytes at pos_in of the source file into implementation should remap len bytes at pos_in of the source file into
the dest file at pos_out. Implementations must handle callers passing the dest file at pos_out. Implementations must handle callers passing
in len == 0; this means "remap to the end of the source file". The in len == 0; this means "remap to the end of the source file". The
return value should be zero if all bytes were remapped, or the usual return value should the number of bytes remapped, or the usual
negative error code if the remapping did not succeed completely. negative error code if errors occurred before any bytes were remapped.
The remap_flags parameter accepts REMAP_FILE_* flags. If The remap_flags parameter accepts REMAP_FILE_* flags. If
REMAP_FILE_DEDUP is set then the implementation must only remap if the REMAP_FILE_DEDUP is set then the implementation must only remap if the
requested file ranges have identical contents. requested file ranges have identical contents.
......
...@@ -3247,9 +3247,9 @@ int btrfs_dirty_pages(struct inode *inode, struct page **pages, ...@@ -3247,9 +3247,9 @@ int btrfs_dirty_pages(struct inode *inode, struct page **pages,
size_t num_pages, loff_t pos, size_t write_bytes, size_t num_pages, loff_t pos, size_t write_bytes,
struct extent_state **cached); struct extent_state **cached);
int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end); int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end);
int btrfs_remap_file_range(struct file *file_in, loff_t pos_in, loff_t btrfs_remap_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, u64 len, struct file *file_out, loff_t pos_out,
unsigned int remap_flags); loff_t len, unsigned int remap_flags);
/* tree-defrag.c */ /* tree-defrag.c */
int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
......
...@@ -4328,10 +4328,12 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src, ...@@ -4328,10 +4328,12 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
return ret; return ret;
} }
int btrfs_remap_file_range(struct file *src_file, loff_t off, loff_t btrfs_remap_file_range(struct file *src_file, loff_t off,
struct file *dst_file, loff_t destoff, u64 len, struct file *dst_file, loff_t destoff, loff_t len,
unsigned int remap_flags) unsigned int remap_flags)
{ {
int ret;
if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
return -EINVAL; return -EINVAL;
...@@ -4349,10 +4351,11 @@ int btrfs_remap_file_range(struct file *src_file, loff_t off, ...@@ -4349,10 +4351,11 @@ int btrfs_remap_file_range(struct file *src_file, loff_t off,
return -EINVAL; return -EINVAL;
} }
return btrfs_extent_same(src, off, len, dst, destoff); ret = btrfs_extent_same(src, off, len, dst, destoff);
} else {
ret = btrfs_clone_files(dst_file, src_file, off, len, destoff);
} }
return ret < 0 ? ret : len;
return btrfs_clone_files(dst_file, src_file, off, len, destoff);
} }
static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
......
...@@ -975,8 +975,8 @@ const struct inode_operations cifs_symlink_inode_ops = { ...@@ -975,8 +975,8 @@ const struct inode_operations cifs_symlink_inode_ops = {
.listxattr = cifs_listxattr, .listxattr = cifs_listxattr,
}; };
static int cifs_remap_file_range(struct file *src_file, loff_t off, static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
struct file *dst_file, loff_t destoff, u64 len, struct file *dst_file, loff_t destoff, loff_t len,
unsigned int remap_flags) unsigned int remap_flags)
{ {
struct inode *src_inode = file_inode(src_file); 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,7 +1029,7 @@ static int cifs_remap_file_range(struct file *src_file, loff_t off,
unlock_two_nondirectories(src_inode, target_inode); unlock_two_nondirectories(src_inode, target_inode);
out: out:
free_xid(xid); free_xid(xid);
return rc; return rc < 0 ? rc : len;
} }
ssize_t cifs_file_copychunk_range(unsigned int xid, ssize_t cifs_file_copychunk_range(unsigned int xid,
......
...@@ -223,6 +223,7 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd, ...@@ -223,6 +223,7 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
u64 off, u64 olen, u64 destoff) u64 off, u64 olen, u64 destoff)
{ {
struct fd src_file = fdget(srcfd); struct fd src_file = fdget(srcfd);
loff_t cloned;
int ret; int ret;
if (!src_file.file) if (!src_file.file)
...@@ -230,7 +231,14 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd, ...@@ -230,7 +231,14 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
ret = -EXDEV; ret = -EXDEV;
if (src_file.file->f_path.mnt != dst_file->f_path.mnt) if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
goto fdput; goto fdput;
ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen); cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff,
olen);
if (cloned < 0)
ret = cloned;
else if (olen && cloned != olen)
ret = -EINVAL;
else
ret = 0;
fdput: fdput:
fdput(src_file); fdput(src_file);
return ret; return ret;
......
...@@ -180,8 +180,8 @@ static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t ...@@ -180,8 +180,8 @@ static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t
return nfs42_proc_allocate(filep, offset, len); return nfs42_proc_allocate(filep, offset, len);
} }
static int nfs42_remap_file_range(struct file *src_file, loff_t src_off, static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
struct file *dst_file, loff_t dst_off, u64 count, struct file *dst_file, loff_t dst_off, loff_t count,
unsigned int remap_flags) unsigned int remap_flags)
{ {
struct inode *dst_inode = file_inode(dst_file); struct inode *dst_inode = file_inode(dst_file);
...@@ -244,7 +244,7 @@ static int nfs42_remap_file_range(struct file *src_file, loff_t src_off, ...@@ -244,7 +244,7 @@ static int nfs42_remap_file_range(struct file *src_file, loff_t src_off,
inode_unlock(src_inode); inode_unlock(src_inode);
} }
out: out:
return ret; return ret < 0 ? ret : count;
} }
#endif /* CONFIG_NFS_V4_2 */ #endif /* CONFIG_NFS_V4_2 */
......
...@@ -541,8 +541,12 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -541,8 +541,12 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
__be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
u64 dst_pos, u64 count) u64 dst_pos, u64 count)
{ {
return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos, loff_t cloned;
count));
cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count);
if (count && cloned != count)
cloned = -EINVAL;
return nfserrno(cloned < 0 ? cloned : 0);
} }
ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst, ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
......
...@@ -2527,18 +2527,18 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence) ...@@ -2527,18 +2527,18 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence)
return offset; return offset;
} }
static int ocfs2_remap_file_range(struct file *file_in, static loff_t ocfs2_remap_file_range(struct file *file_in, loff_t pos_in,
loff_t pos_in, struct file *file_out, loff_t pos_out,
struct file *file_out, loff_t len, unsigned int remap_flags)
loff_t pos_out,
u64 len,
unsigned int remap_flags)
{ {
int ret;
if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
return -EINVAL; return -EINVAL;
return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, ret = ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out,
len, remap_flags); len, remap_flags);
return ret < 0 ? ret : len;
} }
const struct inode_operations ocfs2_file_iops = { const struct inode_operations ocfs2_file_iops = {
......
...@@ -4824,7 +4824,7 @@ int ocfs2_reflink_remap_range(struct file *file_in, ...@@ -4824,7 +4824,7 @@ int ocfs2_reflink_remap_range(struct file *file_in,
loff_t pos_in, loff_t pos_in,
struct file *file_out, struct file *file_out,
loff_t pos_out, loff_t pos_out,
u64 len, loff_t len,
unsigned int remap_flags) unsigned int remap_flags)
{ {
struct inode *inode_in = file_inode(file_in); struct inode *inode_in = file_inode(file_in);
......
...@@ -119,7 +119,7 @@ int ocfs2_reflink_remap_range(struct file *file_in, ...@@ -119,7 +119,7 @@ int ocfs2_reflink_remap_range(struct file *file_in,
loff_t pos_in, loff_t pos_in,
struct file *file_out, struct file *file_out,
loff_t pos_out, loff_t pos_out,
u64 len, loff_t len,
unsigned int remap_flags); unsigned int remap_flags);
#endif /* OCFS2_REFCOUNTTREE_H */ #endif /* OCFS2_REFCOUNTTREE_H */
...@@ -125,6 +125,7 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) ...@@ -125,6 +125,7 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
struct file *new_file; struct file *new_file;
loff_t old_pos = 0; loff_t old_pos = 0;
loff_t new_pos = 0; loff_t new_pos = 0;
loff_t cloned;
int error = 0; int error = 0;
if (len == 0) if (len == 0)
...@@ -141,11 +142,10 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) ...@@ -141,11 +142,10 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
} }
/* Try to use clone_file_range to clone up within the same fs */ /* Try to use clone_file_range to clone up within the same fs */
error = do_clone_file_range(old_file, 0, new_file, 0, len); cloned = do_clone_file_range(old_file, 0, new_file, 0, len);
if (!error) if (cloned == len)
goto out; goto out;
/* Couldn't clone, so now we try to copy the data */ /* Couldn't clone, so now we try to copy the data */
error = 0;
/* FIXME: copy up sparse files efficiently */ /* FIXME: copy up sparse files efficiently */
while (len) { while (len) {
......
...@@ -434,14 +434,14 @@ enum ovl_copyop { ...@@ -434,14 +434,14 @@ enum ovl_copyop {
OVL_DEDUPE, OVL_DEDUPE,
}; };
static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
u64 len, unsigned int flags, enum ovl_copyop op) loff_t len, unsigned int flags, enum ovl_copyop op)
{ {
struct inode *inode_out = file_inode(file_out); struct inode *inode_out = file_inode(file_out);
struct fd real_in, real_out; struct fd real_in, real_out;
const struct cred *old_cred; const struct cred *old_cred;
ssize_t ret; loff_t ret;
ret = ovl_real_fdget(file_out, &real_out); ret = ovl_real_fdget(file_out, &real_out);
if (ret) if (ret)
...@@ -489,9 +489,9 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in, ...@@ -489,9 +489,9 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in,
OVL_COPY); OVL_COPY);
} }
static int ovl_remap_file_range(struct file *file_in, loff_t pos_in, static loff_t ovl_remap_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
u64 len, unsigned int remap_flags) loff_t len, unsigned int remap_flags)
{ {
enum ovl_copyop op; enum ovl_copyop op;
......
...@@ -1589,10 +1589,13 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, ...@@ -1589,10 +1589,13 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
* more efficient if both clone and copy are supported (e.g. NFS). * more efficient if both clone and copy are supported (e.g. NFS).
*/ */
if (file_in->f_op->remap_file_range) { if (file_in->f_op->remap_file_range) {
ret = file_in->f_op->remap_file_range(file_in, pos_in, loff_t cloned;
file_out, pos_out, len, 0);
if (ret == 0) { cloned = file_in->f_op->remap_file_range(file_in, pos_in,
ret = len; file_out, pos_out,
min_t(loff_t, MAX_RW_COUNT, len), 0);
if (cloned > 0) {
ret = cloned;
goto done; goto done;
} }
} }
...@@ -1686,11 +1689,12 @@ SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in, ...@@ -1686,11 +1689,12 @@ SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in,
return ret; return ret;
} }
static int remap_verify_area(struct file *file, loff_t pos, u64 len, bool write) static int remap_verify_area(struct file *file, loff_t pos, loff_t len,
bool write)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
if (unlikely(pos < 0)) if (unlikely(pos < 0 || len < 0))
return -EINVAL; return -EINVAL;
if (unlikely((loff_t) (pos + len) < 0)) 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) ...@@ -1721,7 +1725,7 @@ static int remap_verify_area(struct file *file, loff_t pos, u64 len, bool write)
static int generic_remap_check_len(struct inode *inode_in, static int generic_remap_check_len(struct inode *inode_in,
struct inode *inode_out, struct inode *inode_out,
loff_t pos_out, loff_t pos_out,
u64 *len, loff_t *len,
unsigned int remap_flags) unsigned int remap_flags)
{ {
u64 blkmask = i_blocksize(inode_in) - 1; u64 blkmask = i_blocksize(inode_in) - 1;
...@@ -1747,7 +1751,7 @@ static int generic_remap_check_len(struct inode *inode_in, ...@@ -1747,7 +1751,7 @@ static int generic_remap_check_len(struct inode *inode_in,
*/ */
int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
u64 *len, unsigned int remap_flags) loff_t *len, unsigned int remap_flags)
{ {
struct inode *inode_in = file_inode(file_in); struct inode *inode_in = file_inode(file_in);
struct inode *inode_out = file_inode(file_out); 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,12 +1847,12 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
} }
EXPORT_SYMBOL(generic_remap_file_range_prep); EXPORT_SYMBOL(generic_remap_file_range_prep);
int do_clone_file_range(struct file *file_in, loff_t pos_in, loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, u64 len) struct file *file_out, loff_t pos_out, loff_t len)
{ {
struct inode *inode_in = file_inode(file_in); struct inode *inode_in = file_inode(file_in);
struct inode *inode_out = file_inode(file_out); struct inode *inode_out = file_inode(file_out);
int ret; loff_t ret;
if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
return -EISDIR; return -EISDIR;
...@@ -1881,19 +1885,19 @@ int do_clone_file_range(struct file *file_in, loff_t pos_in, ...@@ -1881,19 +1885,19 @@ int do_clone_file_range(struct file *file_in, loff_t pos_in,
ret = file_in->f_op->remap_file_range(file_in, pos_in, ret = file_in->f_op->remap_file_range(file_in, pos_in,
file_out, pos_out, len, 0); file_out, pos_out, len, 0);
if (!ret) { if (ret < 0)
fsnotify_access(file_in); return ret;
fsnotify_modify(file_out);
}
fsnotify_access(file_in);
fsnotify_modify(file_out);
return ret; return ret;
} }
EXPORT_SYMBOL(do_clone_file_range); EXPORT_SYMBOL(do_clone_file_range);
int vfs_clone_file_range(struct file *file_in, loff_t pos_in, loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, u64 len) struct file *file_out, loff_t pos_out, loff_t len)
{ {
int ret; loff_t ret;
file_start_write(file_out); file_start_write(file_out);
ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len); ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len);
...@@ -1999,10 +2003,11 @@ int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, ...@@ -1999,10 +2003,11 @@ int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
} }
EXPORT_SYMBOL(vfs_dedupe_file_range_compare); EXPORT_SYMBOL(vfs_dedupe_file_range_compare);
int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
struct file *dst_file, loff_t dst_pos, u64 len) struct file *dst_file, loff_t dst_pos,
loff_t len)
{ {
s64 ret; loff_t ret;
ret = mnt_want_write_file(dst_file); ret = mnt_want_write_file(dst_file);
if (ret) if (ret)
...@@ -2051,7 +2056,7 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) ...@@ -2051,7 +2056,7 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
int i; int i;
int ret; int ret;
u16 count = same->dest_count; u16 count = same->dest_count;
int deduped; loff_t deduped;
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))
return -EINVAL; return -EINVAL;
......
...@@ -919,20 +919,23 @@ xfs_file_fallocate( ...@@ -919,20 +919,23 @@ xfs_file_fallocate(
return error; return error;
} }
STATIC int STATIC loff_t
xfs_file_remap_range( xfs_file_remap_range(
struct file *file_in, struct file *file_in,
loff_t pos_in, loff_t pos_in,
struct file *file_out, struct file *file_out,
loff_t pos_out, loff_t pos_out,
u64 len, loff_t len,
unsigned int remap_flags) unsigned int remap_flags)
{ {
int ret;
if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
return -EINVAL; return -EINVAL;
return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out, ret = xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out,
len, remap_flags); len, remap_flags);
return ret < 0 ? ret : len;
} }
STATIC int STATIC int
......
...@@ -1296,7 +1296,7 @@ xfs_reflink_remap_prep( ...@@ -1296,7 +1296,7 @@ xfs_reflink_remap_prep(
loff_t pos_in, loff_t pos_in,
struct file *file_out, struct file *file_out,
loff_t pos_out, loff_t pos_out,
u64 *len, loff_t *len,
unsigned int remap_flags) unsigned int remap_flags)
{ {
struct inode *inode_in = file_inode(file_in); struct inode *inode_in = file_inode(file_in);
...@@ -1387,7 +1387,7 @@ xfs_reflink_remap_range( ...@@ -1387,7 +1387,7 @@ xfs_reflink_remap_range(
loff_t pos_in, loff_t pos_in,
struct file *file_out, struct file *file_out,
loff_t pos_out, loff_t pos_out,
u64 len, loff_t len,
unsigned int remap_flags) unsigned int remap_flags)
{ {
struct inode *inode_in = file_inode(file_in); struct inode *inode_in = file_inode(file_in);
......
...@@ -28,7 +28,7 @@ extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, ...@@ -28,7 +28,7 @@ extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset,
xfs_off_t count); xfs_off_t count);
extern int xfs_reflink_recover_cow(struct xfs_mount *mp); extern int xfs_reflink_recover_cow(struct xfs_mount *mp);
extern int xfs_reflink_remap_range(struct file *file_in, loff_t pos_in, extern int xfs_reflink_remap_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, u64 len, struct file *file_out, loff_t pos_out, loff_t len,
unsigned int remap_flags); unsigned int remap_flags);
extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp, extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp,
struct xfs_inode *ip, bool *has_shared); struct xfs_inode *ip, bool *has_shared);
......
...@@ -1777,9 +1777,9 @@ struct file_operations { ...@@ -1777,9 +1777,9 @@ struct file_operations {
#endif #endif
ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
loff_t, size_t, unsigned int); loff_t, size_t, unsigned int);
int (*remap_file_range)(struct file *file_in, loff_t pos_in, loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
u64 len, unsigned int remap_flags); loff_t len, unsigned int remap_flags);
int (*fadvise)(struct file *, loff_t, loff_t, int); int (*fadvise)(struct file *, loff_t, loff_t, int);
} __randomize_layout; } __randomize_layout;
...@@ -1844,19 +1844,22 @@ extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, ...@@ -1844,19 +1844,22 @@ extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *,
loff_t, size_t, unsigned int); loff_t, size_t, unsigned int);
extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
u64 *count, unsigned int remap_flags); loff_t *count,
extern int do_clone_file_range(struct file *file_in, loff_t pos_in, unsigned int remap_flags);
struct file *file_out, loff_t pos_out, u64 len); extern loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out,
struct file *file_out, loff_t pos_out, u64 len); loff_t len);
extern loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
loff_t len);
extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
struct inode *dest, loff_t destoff, struct inode *dest, loff_t destoff,
loff_t len, bool *is_same); loff_t len, bool *is_same);
extern int vfs_dedupe_file_range(struct file *file, extern int vfs_dedupe_file_range(struct file *file,
struct file_dedupe_range *same); struct file_dedupe_range *same);
extern int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, extern loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
struct file *dst_file, loff_t dst_pos, struct file *dst_file, loff_t dst_pos,
u64 len); loff_t len);
struct super_operations { struct super_operations {
...@@ -2986,7 +2989,7 @@ extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); ...@@ -2986,7 +2989,7 @@ extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *); extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *);
extern int generic_remap_checks(struct file *file_in, loff_t pos_in, extern int generic_remap_checks(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
uint64_t *count, unsigned int remap_flags); loff_t *count, unsigned int remap_flags);
extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *);
extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *);
extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *);
......
...@@ -2994,7 +2994,7 @@ EXPORT_SYMBOL(generic_write_checks); ...@@ -2994,7 +2994,7 @@ EXPORT_SYMBOL(generic_write_checks);
*/ */
int generic_remap_checks(struct file *file_in, loff_t pos_in, int generic_remap_checks(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, struct file *file_out, loff_t pos_out,
uint64_t *req_count, unsigned int remap_flags) loff_t *req_count, unsigned int remap_flags)
{ {
struct inode *inode_in = file_in->f_mapping->host; struct inode *inode_in = file_in->f_mapping->host;
struct inode *inode_out = file_out->f_mapping->host; struct inode *inode_out = file_out->f_mapping->host;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment