From: Bryan Schumaker <bjschuma@xxxxxxxxxx> I added in a fallback to do_splice_direct() if the filesystem doesn't support the copy_range call. This is because the declaration of do_splice_direct() is now found in fs/internal.h and can't be used by other filesystems. I also had to add sys_copy_range to include/linux/syscalls.h to get my test program to recognize the new syscall. Other thoughts: - Pass count = 0 to mean "copy the entire file" - rw_verify_area() limits count to values that can fit in an int, so files larger than about 2GB cannot be copied. --- fs/copy_range.c | 10 +++++++--- include/linux/syscalls.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/copy_range.c b/fs/copy_range.c index 3000b9f..bcf6e67 100644 --- a/fs/copy_range.c +++ b/fs/copy_range.c @@ -10,6 +10,8 @@ #include <linux/export.h> #include <linux/fsnotify.h> +#include "internal.h" + /** * vfs_copy_range - copy range of bytes from source file to existing file * @file_in: source regular file @@ -52,7 +54,7 @@ ssize_t vfs_copy_range(struct file *file_in, loff_t pos_in, if (!(file_in->f_mode & FMODE_READ) || !(file_out->f_mode & FMODE_WRITE) || (file_out->f_flags & O_APPEND) || - !file_in->f_op || !file_in->f_op->copy_range) + !file_in->f_op) return -EINVAL; inode_in = file_inode(file_in); @@ -82,8 +84,10 @@ ssize_t vfs_copy_range(struct file *file_in, loff_t pos_in, if (ret) return ret; - ret = file_in->f_op->copy_range(file_in, pos_in, file_out, pos_out, - count); + if (file_in->f_op->copy_range) + ret = file_in->f_op->copy_range(file_in, pos_in, file_out, pos_out, count); + else + ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out, count, 0); if (ret > 0) { fsnotify_access(file_in); add_rchar(current, ret); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 4147d70..5afcd00 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -485,6 +485,7 @@ asmlinkage long sys_sendfile(int out_fd, int in_fd, off_t __user *offset, size_t count); asmlinkage long sys_sendfile64(int out_fd, int in_fd, loff_t __user *offset, size_t count); +asmlinkage long sys_copy_range(int, loff_t __user *, int, loff_t __user *, size_t); asmlinkage long sys_readlink(const char __user *path, char __user *buf, int bufsiz); asmlinkage long sys_creat(const char __user *pathname, umode_t mode); -- 1.8.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html