summaryrefslogtreecommitdiffstats
path: root/fs/pipe.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-02-03 19:11:42 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-04-01 23:19:22 -0400
commit637b58c2887e5e57850865839cc75f59184b23d1 (patch)
tree96ea83eabcdc3e37c866eda374d079b40b2d4379 /fs/pipe.c
parent74027f4a181754e917853bd1d2e21449f008ab39 (diff)
switch pipe_read() to copy_page_to_iter()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/pipe.c')
-rw-r--r--fs/pipe.c79
1 files changed, 8 insertions, 71 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index 6679c95eb4c3..034bffac3f97 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -142,55 +142,6 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len,
142 return 0; 142 return 0;
143} 143}
144 144
145static int
146pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len,
147 int atomic)
148{
149 unsigned long copy;
150
151 while (len > 0) {
152 while (!iov->iov_len)
153 iov++;
154 copy = min_t(unsigned long, len, iov->iov_len);
155
156 if (atomic) {
157 if (__copy_to_user_inatomic(iov->iov_base, from, copy))
158 return -EFAULT;
159 } else {
160 if (copy_to_user(iov->iov_base, from, copy))
161 return -EFAULT;
162 }
163 from += copy;
164 len -= copy;
165 iov->iov_base += copy;
166 iov->iov_len -= copy;
167 }
168 return 0;
169}
170
171/*
172 * Attempt to pre-fault in the user memory, so we can use atomic copies.
173 * Returns the number of bytes not faulted in.
174 */
175static int iov_fault_in_pages_write(struct iovec *iov, unsigned long len)
176{
177 while (!iov->iov_len)
178 iov++;
179
180 while (len > 0) {
181 unsigned long this_len;
182
183 this_len = min_t(unsigned long, len, iov->iov_len);
184 if (fault_in_pages_writeable(iov->iov_base, this_len))
185 break;
186
187 len -= this_len;
188 iov++;
189 }
190
191 return len;
192}
193
194/* 145/*
195 * Pre-fault in the user memory, so we can use atomic copies. 146 * Pre-fault in the user memory, so we can use atomic copies.
196 */ 147 */
@@ -329,12 +280,15 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
329 ssize_t ret; 280 ssize_t ret;
330 struct iovec *iov = (struct iovec *)_iov; 281 struct iovec *iov = (struct iovec *)_iov;
331 size_t total_len; 282 size_t total_len;
283 struct iov_iter iter;
332 284
333 total_len = iov_length(iov, nr_segs); 285 total_len = iov_length(iov, nr_segs);
334 /* Null read succeeds. */ 286 /* Null read succeeds. */
335 if (unlikely(total_len == 0)) 287 if (unlikely(total_len == 0))
336 return 0; 288 return 0;
337 289
290 iov_iter_init(&iter, iov, nr_segs, total_len, 0);
291
338 do_wakeup = 0; 292 do_wakeup = 0;
339 ret = 0; 293 ret = 0;
340 __pipe_lock(pipe); 294 __pipe_lock(pipe);
@@ -344,9 +298,9 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
344 int curbuf = pipe->curbuf; 298 int curbuf = pipe->curbuf;
345 struct pipe_buffer *buf = pipe->bufs + curbuf; 299 struct pipe_buffer *buf = pipe->bufs + curbuf;
346 const struct pipe_buf_operations *ops = buf->ops; 300 const struct pipe_buf_operations *ops = buf->ops;
347 void *addr;
348 size_t chars = buf->len; 301 size_t chars = buf->len;
349 int error, atomic; 302 size_t written;
303 int error;
350 304
351 if (chars > total_len) 305 if (chars > total_len)
352 chars = total_len; 306 chars = total_len;
@@ -358,27 +312,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
358 break; 312 break;
359 } 313 }
360 314
361 atomic = !iov_fault_in_pages_write(iov, chars); 315 written = copy_page_to_iter(buf->page, buf->offset, chars, &iter);
362redo: 316 if (unlikely(written < chars)) {
363 if (atomic)
364 addr = kmap_atomic(buf->page);
365 else
366 addr = kmap(buf->page);
367 error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic);
368 if (atomic)
369 kunmap_atomic(addr);
370 else
371 kunmap(buf->page);
372 if (unlikely(error)) {
373 /*
374 * Just retry with the slow path if we failed.
375 */
376 if (atomic) {
377 atomic = 0;
378 goto redo;
379 }
380 if (!ret) 317 if (!ret)
381 ret = error; 318 ret = -EFAULT;
382 break; 319 break;
383 } 320 }
384 ret += chars; 321 ret += chars;