Eliminate the #ifdef CONFIG_NET from fs/splice.c and move the splice_to_socket helper to net/socket.c, where the other splice socket helpers live (like sock_splice_read and sock_splice_eof). Signed-off-by: Joe Damato <jdamato@xxxxxxxxxx> --- fs/splice.c | 140 ----------------------------------------- include/linux/splice.h | 3 - net/socket.c | 140 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 143 deletions(-) diff --git a/fs/splice.c b/fs/splice.c index dcd594a8fc06..40b96387a515 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -766,146 +766,6 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, EXPORT_SYMBOL(iter_file_splice_write); -#ifdef CONFIG_NET -/** - * splice_to_socket - splice data from a pipe to a socket - * @pipe: pipe to splice from - * @out: socket to write to - * @ppos: position in @out - * @len: number of bytes to splice - * @flags: splice modifier flags - * - * Description: - * Will send @len bytes from the pipe to a network socket. No data copying - * is involved. - * - */ -ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, - loff_t *ppos, size_t len, unsigned int flags) -{ - struct socket *sock = sock_from_file(out); - struct bio_vec bvec[16]; - struct msghdr msg = {}; - ssize_t ret = 0; - size_t spliced = 0; - bool need_wakeup = false; - - pipe_lock(pipe); - - while (len > 0) { - unsigned int head, tail, mask, bc = 0; - size_t remain = len; - - /* - * Check for signal early to make process killable when there - * are always buffers available - */ - ret = -ERESTARTSYS; - if (signal_pending(current)) - break; - - while (pipe_empty(pipe->head, pipe->tail)) { - ret = 0; - if (!pipe->writers) - goto out; - - if (spliced) - goto out; - - ret = -EAGAIN; - if (flags & SPLICE_F_NONBLOCK) - goto out; - - ret = -ERESTARTSYS; - if (signal_pending(current)) - goto out; - - if (need_wakeup) { - pipe_wakeup_writers(pipe); - need_wakeup = false; - } - - pipe_wait_readable(pipe); - } - - head = pipe->head; - tail = pipe->tail; - mask = pipe->ring_size - 1; - - while (!pipe_empty(head, tail)) { - struct pipe_buffer *buf = &pipe->bufs[tail & mask]; - size_t seg; - - if (!buf->len) { - tail++; - continue; - } - - seg = min_t(size_t, remain, buf->len); - - ret = pipe_buf_confirm(pipe, buf); - if (unlikely(ret)) { - if (ret == -ENODATA) - ret = 0; - break; - } - - bvec_set_page(&bvec[bc++], buf->page, seg, buf->offset); - remain -= seg; - if (remain == 0 || bc >= ARRAY_SIZE(bvec)) - break; - tail++; - } - - if (!bc) - break; - - msg.msg_flags = MSG_SPLICE_PAGES; - if (flags & SPLICE_F_MORE) - msg.msg_flags |= MSG_MORE; - if (remain && pipe_occupancy(pipe->head, tail) > 0) - msg.msg_flags |= MSG_MORE; - if (out->f_flags & O_NONBLOCK) - msg.msg_flags |= MSG_DONTWAIT; - - iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, bvec, bc, - len - remain); - ret = sock_sendmsg(sock, &msg); - if (ret <= 0) - break; - - spliced += ret; - len -= ret; - tail = pipe->tail; - while (ret > 0) { - struct pipe_buffer *buf = &pipe->bufs[tail & mask]; - size_t seg = min_t(size_t, ret, buf->len); - - buf->offset += seg; - buf->len -= seg; - ret -= seg; - - if (!buf->len) { - pipe_buf_release(pipe, buf); - tail++; - } - } - - if (tail != pipe->tail) { - pipe->tail = tail; - if (pipe->files) - need_wakeup = true; - } - } - -out: - pipe_unlock(pipe); - if (need_wakeup) - pipe_wakeup_writers(pipe); - return spliced ?: ret; -} -#endif - static int warn_unsupported(struct file *file, const char *op) { pr_debug_ratelimited( diff --git a/include/linux/splice.h b/include/linux/splice.h index 9dec4861d09f..54c47776469d 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h @@ -97,9 +97,6 @@ static inline long splice_copy_file_range(struct file *in, loff_t pos_in, ssize_t do_tee(struct file *in, struct file *out, size_t len, unsigned int flags); -ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, - loff_t *ppos, size_t len, unsigned int flags); - /* * for dynamic pipe sizing */ diff --git a/net/socket.c b/net/socket.c index 9a117248f18f..2640b42cf320 100644 --- a/net/socket.c +++ b/net/socket.c @@ -132,6 +132,8 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); static void sock_splice_eof(struct file *file); +static ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags); #ifdef CONFIG_PROC_FS static void sock_show_fdinfo(struct seq_file *m, struct file *f) @@ -3719,3 +3721,141 @@ u32 kernel_sock_ip_overhead(struct sock *sk) } } EXPORT_SYMBOL(kernel_sock_ip_overhead); + +/** + * splice_to_socket - splice data from a pipe to a socket + * @pipe: pipe to splice from + * @out: socket to write to + * @ppos: position in @out + * @len: number of bytes to splice + * @flags: splice modifier flags + * + * Description: + * Will send @len bytes from the pipe to a network socket. No data copying + * is involved. + * + */ +static ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) +{ + struct socket *sock = sock_from_file(out); + struct bio_vec bvec[16]; + struct msghdr msg = {}; + ssize_t ret = 0; + size_t spliced = 0; + bool need_wakeup = false; + + pipe_lock(pipe); + + while (len > 0) { + unsigned int head, tail, mask, bc = 0; + size_t remain = len; + + /* + * Check for signal early to make process killable when there + * are always buffers available + */ + ret = -ERESTARTSYS; + if (signal_pending(current)) + break; + + while (pipe_empty(pipe->head, pipe->tail)) { + ret = 0; + if (!pipe->writers) + goto out; + + if (spliced) + goto out; + + ret = -EAGAIN; + if (flags & SPLICE_F_NONBLOCK) + goto out; + + ret = -ERESTARTSYS; + if (signal_pending(current)) + goto out; + + if (need_wakeup) { + pipe_wakeup_writers(pipe); + need_wakeup = false; + } + + pipe_wait_readable(pipe); + } + + head = pipe->head; + tail = pipe->tail; + mask = pipe->ring_size - 1; + + while (!pipe_empty(head, tail)) { + struct pipe_buffer *buf = &pipe->bufs[tail & mask]; + size_t seg; + + if (!buf->len) { + tail++; + continue; + } + + seg = min_t(size_t, remain, buf->len); + + ret = pipe_buf_confirm(pipe, buf); + if (unlikely(ret)) { + if (ret == -ENODATA) + ret = 0; + break; + } + + bvec_set_page(&bvec[bc++], buf->page, seg, buf->offset); + remain -= seg; + if (remain == 0 || bc >= ARRAY_SIZE(bvec)) + break; + tail++; + } + + if (!bc) + break; + + msg.msg_flags = MSG_SPLICE_PAGES; + if (flags & SPLICE_F_MORE) + msg.msg_flags |= MSG_MORE; + if (remain && pipe_occupancy(pipe->head, tail) > 0) + msg.msg_flags |= MSG_MORE; + if (out->f_flags & O_NONBLOCK) + msg.msg_flags |= MSG_DONTWAIT; + + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, bvec, bc, + len - remain); + ret = sock_sendmsg(sock, &msg); + if (ret <= 0) + break; + + spliced += ret; + len -= ret; + tail = pipe->tail; + while (ret > 0) { + struct pipe_buffer *buf = &pipe->bufs[tail & mask]; + size_t seg = min_t(size_t, ret, buf->len); + + buf->offset += seg; + buf->len -= seg; + ret -= seg; + + if (!buf->len) { + pipe_buf_release(pipe, buf); + tail++; + } + } + + if (tail != pipe->tail) { + pipe->tail = tail; + if (pipe->files) + need_wakeup = true; + } + } + +out: + pipe_unlock(pipe); + if (need_wakeup) + pipe_wakeup_writers(pipe); + return spliced ?: ret; +} -- 2.43.0