Now that __kernel_write or __kernel_write don't just work on all file operations instances there is not much of a point of providing default splice methods. Renamed the existing default ones to simple_ and wire them up for the few instancas actually implementing ->read_uptr and ->write_uptr. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- fs/proc/proc_sysctl.c | 2 ++ fs/splice.c | 40 ++++++++++++++++++++++++++++------------ include/linux/fs.h | 5 ++++- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index dd5eb693bd00df..5adbc1c8f899cd 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -856,6 +856,8 @@ static const struct file_operations proc_sys_file_operations = { .poll = proc_sys_poll, .read_uptr = proc_sys_read, .write_uptr = proc_sys_write, + .splice_read = simple_splice_read, + .splice_write = simple_splice_write, .llseek = default_llseek, }; diff --git a/fs/splice.c b/fs/splice.c index d1efc53875bd93..d5bba2cd695b5d 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -342,9 +342,8 @@ const struct pipe_buf_operations nosteal_pipe_buf_ops = { }; EXPORT_SYMBOL(nosteal_pipe_buf_ops); -static ssize_t default_file_splice_read(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) +ssize_t simple_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, unsigned int flags) { struct iov_iter to; struct page **pages; @@ -779,9 +778,8 @@ static int write_pipe_buf(struct pipe_inode_info *pipe, struct pipe_buffer *buf, return ret; } -static ssize_t default_file_splice_write(struct pipe_inode_info *pipe, - struct file *out, loff_t *ppos, - size_t len, unsigned int flags) +ssize_t simple_splice_write(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) { ssize_t ret; @@ -813,15 +811,30 @@ ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, EXPORT_SYMBOL(generic_splice_sendpage); +static void warn_unsupported(struct file *file, const char *op) +{ + char pathname[128], *path; + + path = file_path(file, pathname, sizeof(pathname)); + if (IS_ERR(path)) + path = "(unknown)"; + pr_debug_ratelimited( + "splice %s not supported for file %s (pid: %d comm: %.20s)\n", + op, path, current->pid, current->comm); +} + /* * Attempt to initiate a splice from pipe to file. */ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { - if (out->f_op->splice_write) - return out->f_op->splice_write(pipe, out, ppos, len, flags); - return default_file_splice_write(pipe, out, ppos, len, flags); + if (!out->f_op->splice_write) { + warn_unsupported(out, "write"); + return -EINVAL; + } + + return out->f_op->splice_write(pipe, out, ppos, len, flags); } /* @@ -843,9 +856,12 @@ static long do_splice_to(struct file *in, loff_t *ppos, if (unlikely(len > MAX_RW_COUNT)) len = MAX_RW_COUNT; - if (in->f_op->splice_read) - return in->f_op->splice_read(in, ppos, pipe, len, flags); - return default_file_splice_read(in, ppos, pipe, len, flags); + if (!in->f_op->splice_read) { + warn_unsupported(in, "read"); + return -EINVAL; + } + + return in->f_op->splice_read(in, ppos, pipe, len, flags); } /** diff --git a/include/linux/fs.h b/include/linux/fs.h index d0fea0281ef29b..64a6506cba0446 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3175,7 +3175,10 @@ extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, loff_t *, size_t len, unsigned int flags); extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, loff_t *opos, size_t len, unsigned int flags); - +ssize_t simple_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, unsigned int flags); +ssize_t simple_splice_write(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags); extern void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); -- 2.26.2