Commit 0b0a47f5c4a30b58432e20ae1706a27baea91a88

Authored by Miklos Szeredi
Committed by Jens Axboe
1 parent 6818173bd6

splice: implement default splice_write method

If f_op->splice_write() is not implemented, fall back to a plain write.
Use vfs_writev() to write from the pipe buffers.

This will allow splice on all filesystems and file types.  This
includes "direct_io" files in fuse which bypass the page cache.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

Showing 1 changed file with 138 additions and 4 deletions Side-by-side Diff

... ... @@ -535,6 +535,21 @@
535 535 return res;
536 536 }
537 537  
  538 +static ssize_t kernel_writev(struct file *file, const struct iovec *vec,
  539 + unsigned long vlen, loff_t *ppos)
  540 +{
  541 + mm_segment_t old_fs;
  542 + ssize_t res;
  543 +
  544 + old_fs = get_fs();
  545 + set_fs(get_ds());
  546 + /* The cast to a user pointer is valid due to the set_fs() */
  547 + res = vfs_writev(file, (const struct iovec __user *)vec, vlen, ppos);
  548 + set_fs(old_fs);
  549 +
  550 + return res;
  551 +}
  552 +
538 553 ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
539 554 struct pipe_inode_info *pipe, size_t len,
540 555 unsigned int flags)
... ... @@ -988,6 +1003,122 @@
988 1003  
989 1004 EXPORT_SYMBOL(generic_file_splice_write);
990 1005  
  1006 +static struct pipe_buffer *nth_pipe_buf(struct pipe_inode_info *pipe, int n)
  1007 +{
  1008 + return &pipe->bufs[(pipe->curbuf + n) % PIPE_BUFFERS];
  1009 +}
  1010 +
  1011 +static ssize_t default_file_splice_write(struct pipe_inode_info *pipe,
  1012 + struct file *out, loff_t *ppos,
  1013 + size_t len, unsigned int flags)
  1014 +{
  1015 + ssize_t ret = 0;
  1016 + ssize_t total_len = 0;
  1017 + int do_wakeup = 0;
  1018 +
  1019 + pipe_lock(pipe);
  1020 + while (len) {
  1021 + struct pipe_buffer *buf;
  1022 + void *data[PIPE_BUFFERS];
  1023 + struct iovec vec[PIPE_BUFFERS];
  1024 + unsigned int nr_pages = 0;
  1025 + unsigned int write_len = 0;
  1026 + unsigned int now_len = len;
  1027 + unsigned int this_len;
  1028 + int i;
  1029 +
  1030 + BUG_ON(pipe->nrbufs > PIPE_BUFFERS);
  1031 + for (i = 0; i < pipe->nrbufs && now_len; i++) {
  1032 + buf = nth_pipe_buf(pipe, i);
  1033 +
  1034 + ret = buf->ops->confirm(pipe, buf);
  1035 + if (ret)
  1036 + break;
  1037 +
  1038 + data[i] = buf->ops->map(pipe, buf, 0);
  1039 + this_len = min(buf->len, now_len);
  1040 + vec[i].iov_base = (void __user *) data[i] + buf->offset;
  1041 + vec[i].iov_len = this_len;
  1042 + now_len -= this_len;
  1043 + write_len += this_len;
  1044 + nr_pages++;
  1045 + }
  1046 +
  1047 + if (nr_pages) {
  1048 + ret = kernel_writev(out, vec, nr_pages, ppos);
  1049 + if (ret == 0)
  1050 + ret = -EIO;
  1051 + if (ret > 0) {
  1052 + len -= ret;
  1053 + total_len += ret;
  1054 + }
  1055 + }
  1056 +
  1057 + for (i = 0; i < nr_pages; i++) {
  1058 + buf = nth_pipe_buf(pipe, i);
  1059 + buf->ops->unmap(pipe, buf, data[i]);
  1060 +
  1061 + if (ret > 0) {
  1062 + this_len = min_t(unsigned, vec[i].iov_len, ret);
  1063 + buf->offset += this_len;
  1064 + buf->len -= this_len;
  1065 + ret -= this_len;
  1066 + }
  1067 + }
  1068 +
  1069 + if (ret < 0)
  1070 + break;
  1071 +
  1072 + while (pipe->nrbufs) {
  1073 + const struct pipe_buf_operations *ops;
  1074 +
  1075 + buf = nth_pipe_buf(pipe, 0);
  1076 + if (buf->len)
  1077 + break;
  1078 +
  1079 + ops = buf->ops;
  1080 + buf->ops = NULL;
  1081 + ops->release(pipe, buf);
  1082 + pipe->curbuf = (pipe->curbuf + 1) % PIPE_BUFFERS;
  1083 + pipe->nrbufs--;
  1084 + if (pipe->inode)
  1085 + do_wakeup = 1;
  1086 + }
  1087 +
  1088 + if (pipe->nrbufs)
  1089 + continue;
  1090 + if (!pipe->writers)
  1091 + break;
  1092 + if (!pipe->waiting_writers) {
  1093 + if (total_len)
  1094 + break;
  1095 + }
  1096 +
  1097 + if (flags & SPLICE_F_NONBLOCK) {
  1098 + ret = -EAGAIN;
  1099 + break;
  1100 + }
  1101 +
  1102 + if (signal_pending(current)) {
  1103 + ret = -ERESTARTSYS;
  1104 + break;
  1105 + }
  1106 +
  1107 + if (do_wakeup) {
  1108 + wakeup_pipe_writers(pipe);
  1109 + do_wakeup = 0;
  1110 + }
  1111 +
  1112 + pipe_wait(pipe);
  1113 + }
  1114 + pipe_unlock(pipe);
  1115 +
  1116 + if (do_wakeup)
  1117 + wakeup_pipe_writers(pipe);
  1118 +
  1119 + return total_len ? total_len : ret;
  1120 +}
  1121 +
991 1122 /**
992 1123 * generic_splice_sendpage - splice data from a pipe to a socket
993 1124 * @pipe: pipe to splice from
994 1125  
... ... @@ -1015,11 +1146,10 @@
1015 1146 static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
1016 1147 loff_t *ppos, size_t len, unsigned int flags)
1017 1148 {
  1149 + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
  1150 + loff_t *, size_t, unsigned int);
1018 1151 int ret;
1019 1152  
1020   - if (unlikely(!out->f_op || !out->f_op->splice_write))
1021   - return -EINVAL;
1022   -
1023 1153 if (unlikely(!(out->f_mode & FMODE_WRITE)))
1024 1154 return -EBADF;
1025 1155  
... ... @@ -1030,7 +1160,11 @@
1030 1160 if (unlikely(ret < 0))
1031 1161 return ret;
1032 1162  
1033   - return out->f_op->splice_write(pipe, out, ppos, len, flags);
  1163 + splice_write = out->f_op->splice_write;
  1164 + if (!splice_write)
  1165 + splice_write = default_file_splice_write;
  1166 +
  1167 + return splice_write(pipe, out, ppos, len, flags);
1034 1168 }
1035 1169  
1036 1170 /*