Christoph Hellwig <hch@xxxxxxxxxxxxx> wrote: > The (pre-existing) long here is odd given that ->splice_read > returns a ssize_t. This might be a good time to fix that up. Here's a patch to do that. I'm not sure yet that I've got all the places that need changing as there are a couple of function pointer-taking functions where the pointed-to function return value should be changed. There are a couple of potential bugs fixed here too, where something takes a size_t length, but counts the data spliced in an int. iter_to_pipe() for example. David --- splice: Convert longs and some ints into ssize_t Convert 'long' and some 'int' into ssize_t in the code involved in splice. Suggested-by: Christoph Hellwig <hch@xxxxxx> Signed-off-by: David Howells <dhowells@xxxxxxxxxx> cc: Christoph Hellwig <hch@xxxxxx> cc: Jens Axboe <axboe@xxxxxxxxx> cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> cc: John Hubbard <jhubbard@xxxxxxxxxx> cc: David Hildenbrand <david@xxxxxxxxxx> cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> cc: linux-block@xxxxxxxxxxxxxxx cc: linux-fsdevel@xxxxxxxxxxxxxxx cc: linux-mm@xxxxxxxxx Link: https://lore.kernel.org/r/ZBCvdKQskS46qyV3@xxxxxxxxxxxxx/ --- drivers/char/mem.c | 4 - drivers/char/virtio_console.c | 7 +- fs/splice.c | 119 +++++++++++++++++++++--------------------- include/linux/splice.h | 24 ++++---- 4 files changed, 78 insertions(+), 76 deletions(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index ffb101d349f0..230b72e12c54 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -468,8 +468,8 @@ static ssize_t write_iter_null(struct kiocb *iocb, struct iov_iter *from) return count; } -static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, - struct splice_desc *sd) +static ssize_t pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, + struct splice_desc *sd) { return sd->len; } diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index d5ac4d955bc8..d38bee859d5c 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -854,11 +854,12 @@ struct sg_list { struct scatterlist *sg; }; -static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf, - struct splice_desc *sd) +static ssize_t pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf, + struct splice_desc *sd) { struct sg_list *sgl = sd->u.data; - unsigned int offset, len; + ssize_t len; + size_t offset; if (sgl->n == sgl->size) return 0; diff --git a/fs/splice.c b/fs/splice.c index f46dd1fb367b..2bfa94d21346 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -186,7 +186,8 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe, unsigned int tail = pipe->tail; unsigned int head = pipe->head; unsigned int mask = pipe->ring_size - 1; - int ret = 0, page_nr = 0; + ssize_t ret = 0; + int page_nr = 0; if (!spd_pages) return 0; @@ -232,7 +233,7 @@ ssize_t add_to_pipe(struct pipe_inode_info *pipe, struct pipe_buffer *buf) unsigned int head = pipe->head; unsigned int tail = pipe->tail; unsigned int mask = pipe->ring_size - 1; - int ret; + ssize_t ret; if (unlikely(!pipe->readers)) { send_sig(SIGPIPE, current, 0); @@ -414,8 +415,8 @@ EXPORT_SYMBOL(nosteal_pipe_buf_ops); * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos' * using sendpage(). Return the number of bytes sent. */ -static int pipe_to_sendpage(struct pipe_inode_info *pipe, - struct pipe_buffer *buf, struct splice_desc *sd) +static ssize_t pipe_to_sendpage(struct pipe_inode_info *pipe, + struct pipe_buffer *buf, struct splice_desc *sd) { struct file *file = sd->u.file; loff_t pos = sd->pos; @@ -468,7 +469,7 @@ static int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_des unsigned int head = pipe->head; unsigned int tail = pipe->tail; unsigned int mask = pipe->ring_size - 1; - int ret; + ssize_t ret; while (!pipe_empty(head, tail)) { struct pipe_buffer *buf = &pipe->bufs[tail & mask]; @@ -621,7 +622,7 @@ static void splice_from_pipe_end(struct pipe_inode_info *pipe, struct splice_des ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, splice_actor *actor) { - int ret; + ssize_t ret; splice_from_pipe_begin(sd); do { @@ -827,8 +828,8 @@ static int warn_unsupported(struct file *file, const char *op) /* * 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) +static ssize_t do_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) { if (unlikely(!out->f_op->splice_write)) return warn_unsupported(out, "write"); @@ -850,12 +851,12 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, * If successful, it returns the amount of data spliced, 0 if it hit the EOF or * a hole and a negative error code otherwise. */ -long vfs_splice_read(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) +ssize_t vfs_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { unsigned int p_space; - int ret; + ssize_t ret; if (unlikely(!(in->f_mode & FMODE_READ))) return -EBADF; @@ -894,7 +895,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, splice_direct_actor *actor) { struct pipe_inode_info *pipe; - long ret, bytes; + ssize_t ret, bytes; size_t len; int i, flags, more; @@ -1007,7 +1008,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, } EXPORT_SYMBOL(splice_direct_to_actor); -static int direct_splice_actor(struct pipe_inode_info *pipe, +static ssize_t direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd) { struct file *file = sd->u.file; @@ -1032,8 +1033,8 @@ static int direct_splice_actor(struct pipe_inode_info *pipe, * can splice directly through a process-private pipe. * */ -long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, - loff_t *opos, size_t len, unsigned int flags) +ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out, + loff_t *opos, size_t len, unsigned int flags) { struct splice_desc sd = { .len = len, @@ -1043,7 +1044,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, .u.file = out, .opos = opos, }; - long ret; + ssize_t ret; if (unlikely(!(out->f_mode & FMODE_WRITE))) return -EBADF; @@ -1080,16 +1081,16 @@ static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags) } } -static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, - struct pipe_inode_info *opipe, - size_t len, unsigned int flags); +static ssize_t splice_pipe_to_pipe(struct pipe_inode_info *ipipe, + struct pipe_inode_info *opipe, + size_t len, unsigned int flags); -long splice_file_to_pipe(struct file *in, - struct pipe_inode_info *opipe, - loff_t *offset, - size_t len, unsigned int flags) +ssize_t splice_file_to_pipe(struct file *in, + struct pipe_inode_info *opipe, + loff_t *offset, + size_t len, unsigned int flags) { - long ret; + ssize_t ret; pipe_lock(opipe); ret = wait_for_space(opipe, flags); @@ -1104,13 +1105,13 @@ long splice_file_to_pipe(struct file *in, /* * Determine where to splice to/from. */ -long do_splice(struct file *in, loff_t *off_in, struct file *out, - loff_t *off_out, size_t len, unsigned int flags) +ssize_t do_splice(struct file *in, loff_t *off_in, struct file *out, + loff_t *off_out, size_t len, unsigned int flags) { struct pipe_inode_info *ipipe; struct pipe_inode_info *opipe; loff_t offset; - long ret; + ssize_t ret; if (unlikely(!(in->f_mode & FMODE_READ) || !(out->f_mode & FMODE_WRITE))) @@ -1192,14 +1193,14 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out, return -EINVAL; } -static long __do_splice(struct file *in, loff_t __user *off_in, - struct file *out, loff_t __user *off_out, - size_t len, unsigned int flags) +static ssize_t __do_splice(struct file *in, loff_t __user *off_in, + struct file *out, loff_t __user *off_out, + size_t len, unsigned int flags) { struct pipe_inode_info *ipipe; struct pipe_inode_info *opipe; loff_t offset, *__off_in = NULL, *__off_out = NULL; - long ret; + ssize_t ret; ipipe = get_pipe_info(in, true); opipe = get_pipe_info(out, true); @@ -1232,16 +1233,16 @@ static long __do_splice(struct file *in, loff_t __user *off_in, return ret; } -static int iter_to_pipe(struct iov_iter *from, - struct pipe_inode_info *pipe, - unsigned flags) +static ssize_t iter_to_pipe(struct iov_iter *from, + struct pipe_inode_info *pipe, + unsigned flags) { struct pipe_buffer buf = { .ops = &user_page_pipe_buf_ops, .flags = flags }; size_t total = 0; - int ret = 0; + ssize_t ret = 0; while (iov_iter_count(from)) { struct page *pages[16]; @@ -1257,7 +1258,7 @@ static int iter_to_pipe(struct iov_iter *from, n = DIV_ROUND_UP(left + start, PAGE_SIZE); for (i = 0; i < n; i++) { - int size = min_t(int, left, PAGE_SIZE - start); + size_t size = min_t(int, left, PAGE_SIZE - start); buf.page = pages[i]; buf.offset = start; @@ -1279,10 +1280,10 @@ static int iter_to_pipe(struct iov_iter *from, return total ? total : ret; } -static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, - struct splice_desc *sd) +static ssize_t pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, + struct splice_desc *sd) { - int n = copy_page_to_iter(buf->page, buf->offset, sd->len, sd->u.data); + size_t n = copy_page_to_iter(buf->page, buf->offset, sd->len, sd->u.data); return n == sd->len ? n : -EFAULT; } @@ -1290,8 +1291,8 @@ static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, * For lack of a better implementation, implement vmsplice() to userspace * as a simple copy of the pipes pages to the user iov. */ -static long vmsplice_to_user(struct file *file, struct iov_iter *iter, - unsigned int flags) +static ssize_t vmsplice_to_user(struct file *file, struct iov_iter *iter, + unsigned int flags) { struct pipe_inode_info *pipe = get_pipe_info(file, true); struct splice_desc sd = { @@ -1299,7 +1300,7 @@ static long vmsplice_to_user(struct file *file, struct iov_iter *iter, .flags = flags, .u.data = iter }; - long ret = 0; + ssize_t ret = 0; if (!pipe) return -EBADF; @@ -1318,12 +1319,12 @@ static long vmsplice_to_user(struct file *file, struct iov_iter *iter, * as splice-from-memory, where the regular splice is splice-from-file (or * to file). In both cases the output is a pipe, naturally. */ -static long vmsplice_to_pipe(struct file *file, struct iov_iter *iter, - unsigned int flags) +static ssize_t vmsplice_to_pipe(struct file *file, struct iov_iter *iter, + unsigned int flags) { struct pipe_inode_info *pipe; - long ret = 0; - unsigned buf_flag = 0; + ssize_t ret = 0; + unsigned int buf_flag = 0; if (flags & SPLICE_F_GIFT) buf_flag = PIPE_BUF_FLAG_GIFT; @@ -1414,7 +1415,7 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in, size_t, len, unsigned int, flags) { struct fd in, out; - long error; + ssize_t error; if (unlikely(!len)) return 0; @@ -1514,15 +1515,15 @@ static int opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) /* * Splice contents of ipipe to opipe. */ -static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, - struct pipe_inode_info *opipe, - size_t len, unsigned int flags) +static ssize_t splice_pipe_to_pipe(struct pipe_inode_info *ipipe, + struct pipe_inode_info *opipe, + size_t len, unsigned int flags) { struct pipe_buffer *ibuf, *obuf; unsigned int i_head, o_head; unsigned int i_tail, o_tail; unsigned int i_mask, o_mask; - int ret = 0; + ssize_t ret = 0; bool input_wakeup = false; @@ -1651,15 +1652,15 @@ static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, /* * Link contents of ipipe to opipe. */ -static int link_pipe(struct pipe_inode_info *ipipe, - struct pipe_inode_info *opipe, - size_t len, unsigned int flags) +static ssize_t link_pipe(struct pipe_inode_info *ipipe, + struct pipe_inode_info *opipe, + size_t len, unsigned int flags) { struct pipe_buffer *ibuf, *obuf; unsigned int i_head, o_head; unsigned int i_tail, o_tail; unsigned int i_mask, o_mask; - int ret = 0; + ssize_t ret = 0; /* * Potential ABBA deadlock, work around it by ordering lock @@ -1742,11 +1743,11 @@ static int link_pipe(struct pipe_inode_info *ipipe, * The 'flags' used are the SPLICE_F_* variants, currently the only * applicable one is SPLICE_F_NONBLOCK. */ -long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) +ssize_t do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) { struct pipe_inode_info *ipipe = get_pipe_info(in, true); struct pipe_inode_info *opipe = get_pipe_info(out, true); - int ret = -EINVAL; + ssize_t ret = -EINVAL; if (unlikely(!(in->f_mode & FMODE_READ) || !(out->f_mode & FMODE_WRITE))) @@ -1778,7 +1779,7 @@ long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags) { struct fd in, out; - int error; + ssize_t error; if (unlikely(flags & ~SPLICE_F_ALL)) return -EINVAL; diff --git a/include/linux/splice.h b/include/linux/splice.h index 8f052c3dae95..6af5e197ccd0 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h @@ -62,10 +62,10 @@ struct splice_pipe_desc { void (*spd_release)(struct splice_pipe_desc *, unsigned int); }; -typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, - struct splice_desc *); -typedef int (splice_direct_actor)(struct pipe_inode_info *, - struct splice_desc *); +typedef ssize_t (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, + struct splice_desc *); +typedef ssize_t (splice_direct_actor)(struct pipe_inode_info *, + struct splice_desc *); extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int, @@ -76,17 +76,17 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *, struct splice_pipe_desc *); extern ssize_t add_to_pipe(struct pipe_inode_info *, struct pipe_buffer *); -long vfs_splice_read(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags); +ssize_t vfs_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags); extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, splice_direct_actor *); -extern long do_splice(struct file *in, loff_t *off_in, - struct file *out, loff_t *off_out, - size_t len, unsigned int flags); +extern ssize_t do_splice(struct file *in, loff_t *off_in, + struct file *out, loff_t *off_out, + size_t len, unsigned int flags); -extern long do_tee(struct file *in, struct file *out, size_t len, - unsigned int flags); +extern ssize_t do_tee(struct file *in, struct file *out, size_t len, + unsigned int flags); /* * for dynamic pipe sizing