@@ -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(
@@ -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
*/
@@ -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;
+}
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@fastly.com> --- fs/splice.c | 140 ----------------------------------------- include/linux/splice.h | 3 - net/socket.c | 140 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 143 deletions(-)