diff options
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 43 |
1 files changed, 20 insertions, 23 deletions
diff --git a/fs/splice.c b/fs/splice.c index ed2ce995475c..6c9828651e6f 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/syscalls.h> | 29 | #include <linux/syscalls.h> |
30 | #include <linux/uio.h> | 30 | #include <linux/uio.h> |
31 | #include <linux/security.h> | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * Attempt to steal a page from a pipe buffer. This should perhaps go into | 34 | * Attempt to steal a page from a pipe buffer. This should perhaps go into |
@@ -491,7 +492,7 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
491 | 492 | ||
492 | ret = 0; | 493 | ret = 0; |
493 | spliced = 0; | 494 | spliced = 0; |
494 | while (len) { | 495 | while (len && !spliced) { |
495 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); | 496 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); |
496 | 497 | ||
497 | if (ret < 0) | 498 | if (ret < 0) |
@@ -961,6 +962,10 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | |||
961 | if (unlikely(ret < 0)) | 962 | if (unlikely(ret < 0)) |
962 | return ret; | 963 | return ret; |
963 | 964 | ||
965 | ret = security_file_permission(out, MAY_WRITE); | ||
966 | if (unlikely(ret < 0)) | ||
967 | return ret; | ||
968 | |||
964 | return out->f_op->splice_write(pipe, out, ppos, len, flags); | 969 | return out->f_op->splice_write(pipe, out, ppos, len, flags); |
965 | } | 970 | } |
966 | 971 | ||
@@ -983,6 +988,10 @@ static long do_splice_to(struct file *in, loff_t *ppos, | |||
983 | if (unlikely(ret < 0)) | 988 | if (unlikely(ret < 0)) |
984 | return ret; | 989 | return ret; |
985 | 990 | ||
991 | ret = security_file_permission(in, MAY_READ); | ||
992 | if (unlikely(ret < 0)) | ||
993 | return ret; | ||
994 | |||
986 | return in->f_op->splice_read(in, ppos, pipe, len, flags); | 995 | return in->f_op->splice_read(in, ppos, pipe, len, flags); |
987 | } | 996 | } |
988 | 997 | ||
@@ -1051,15 +1060,10 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | |||
1051 | sd->flags &= ~SPLICE_F_NONBLOCK; | 1060 | sd->flags &= ~SPLICE_F_NONBLOCK; |
1052 | 1061 | ||
1053 | while (len) { | 1062 | while (len) { |
1054 | size_t read_len, max_read_len; | 1063 | size_t read_len; |
1055 | |||
1056 | /* | ||
1057 | * Do at most PIPE_BUFFERS pages worth of transfer: | ||
1058 | */ | ||
1059 | max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); | ||
1060 | 1064 | ||
1061 | ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags); | 1065 | ret = do_splice_to(in, &sd->pos, pipe, len, flags); |
1062 | if (unlikely(ret < 0)) | 1066 | if (unlikely(ret <= 0)) |
1063 | goto out_release; | 1067 | goto out_release; |
1064 | 1068 | ||
1065 | read_len = ret; | 1069 | read_len = ret; |
@@ -1071,26 +1075,17 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | |||
1071 | * could get stuck data in the internal pipe: | 1075 | * could get stuck data in the internal pipe: |
1072 | */ | 1076 | */ |
1073 | ret = actor(pipe, sd); | 1077 | ret = actor(pipe, sd); |
1074 | if (unlikely(ret < 0)) | 1078 | if (unlikely(ret <= 0)) |
1075 | goto out_release; | 1079 | goto out_release; |
1076 | 1080 | ||
1077 | bytes += ret; | 1081 | bytes += ret; |
1078 | len -= ret; | 1082 | len -= ret; |
1079 | 1083 | ||
1080 | /* | 1084 | if (ret < read_len) |
1081 | * In nonblocking mode, if we got back a short read then | 1085 | goto out_release; |
1082 | * that was due to either an IO error or due to the | ||
1083 | * pagecache entry not being there. In the IO error case | ||
1084 | * the _next_ splice attempt will produce a clean IO error | ||
1085 | * return value (not a short read), so in both cases it's | ||
1086 | * correct to break out of the loop here: | ||
1087 | */ | ||
1088 | if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len)) | ||
1089 | break; | ||
1090 | } | 1086 | } |
1091 | 1087 | ||
1092 | pipe->nrbufs = pipe->curbuf = 0; | 1088 | pipe->nrbufs = pipe->curbuf = 0; |
1093 | |||
1094 | return bytes; | 1089 | return bytes; |
1095 | 1090 | ||
1096 | out_release: | 1091 | out_release: |
@@ -1152,10 +1147,12 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
1152 | .pos = *ppos, | 1147 | .pos = *ppos, |
1153 | .u.file = out, | 1148 | .u.file = out, |
1154 | }; | 1149 | }; |
1155 | size_t ret; | 1150 | long ret; |
1156 | 1151 | ||
1157 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); | 1152 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); |
1158 | *ppos = sd.pos; | 1153 | if (ret > 0) |
1154 | *ppos += ret; | ||
1155 | |||
1159 | return ret; | 1156 | return ret; |
1160 | } | 1157 | } |
1161 | 1158 | ||