mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
133 lines
3.1 KiB
Diff
133 lines
3.1 KiB
Diff
From 637b58c2887e5e57850865839cc75f59184b23d1 Mon Sep 17 00:00:00 2001
|
|
From: Al Viro <viro@zeniv.linux.org.uk>
|
|
Date: Mon, 3 Feb 2014 19:11:42 -0500
|
|
Subject: switch pipe_read() to copy_page_to_iter()
|
|
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
---
|
|
fs/pipe.c | 79 +++++++--------------------------------------------------------
|
|
1 file changed, 8 insertions(+), 71 deletions(-)
|
|
|
|
diff --git a/fs/pipe.c b/fs/pipe.c
|
|
index 6679c95..034bffa 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,
|
|
return 0;
|
|
}
|
|
|
|
-static int
|
|
-pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len,
|
|
- int atomic)
|
|
-{
|
|
- unsigned long copy;
|
|
-
|
|
- while (len > 0) {
|
|
- while (!iov->iov_len)
|
|
- iov++;
|
|
- copy = min_t(unsigned long, len, iov->iov_len);
|
|
-
|
|
- if (atomic) {
|
|
- if (__copy_to_user_inatomic(iov->iov_base, from, copy))
|
|
- return -EFAULT;
|
|
- } else {
|
|
- if (copy_to_user(iov->iov_base, from, copy))
|
|
- return -EFAULT;
|
|
- }
|
|
- from += copy;
|
|
- len -= copy;
|
|
- iov->iov_base += copy;
|
|
- iov->iov_len -= copy;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Attempt to pre-fault in the user memory, so we can use atomic copies.
|
|
- * Returns the number of bytes not faulted in.
|
|
- */
|
|
-static int iov_fault_in_pages_write(struct iovec *iov, unsigned long len)
|
|
-{
|
|
- while (!iov->iov_len)
|
|
- iov++;
|
|
-
|
|
- while (len > 0) {
|
|
- unsigned long this_len;
|
|
-
|
|
- this_len = min_t(unsigned long, len, iov->iov_len);
|
|
- if (fault_in_pages_writeable(iov->iov_base, this_len))
|
|
- break;
|
|
-
|
|
- len -= this_len;
|
|
- iov++;
|
|
- }
|
|
-
|
|
- return len;
|
|
-}
|
|
-
|
|
/*
|
|
* Pre-fault in the user memory, so we can use atomic copies.
|
|
*/
|
|
@@ -329,12 +280,15 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
|
|
ssize_t ret;
|
|
struct iovec *iov = (struct iovec *)_iov;
|
|
size_t total_len;
|
|
+ struct iov_iter iter;
|
|
|
|
total_len = iov_length(iov, nr_segs);
|
|
/* Null read succeeds. */
|
|
if (unlikely(total_len == 0))
|
|
return 0;
|
|
|
|
+ iov_iter_init(&iter, iov, nr_segs, total_len, 0);
|
|
+
|
|
do_wakeup = 0;
|
|
ret = 0;
|
|
__pipe_lock(pipe);
|
|
@@ -344,9 +298,9 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
|
|
int curbuf = pipe->curbuf;
|
|
struct pipe_buffer *buf = pipe->bufs + curbuf;
|
|
const struct pipe_buf_operations *ops = buf->ops;
|
|
- void *addr;
|
|
size_t chars = buf->len;
|
|
- int error, atomic;
|
|
+ size_t written;
|
|
+ int error;
|
|
|
|
if (chars > total_len)
|
|
chars = total_len;
|
|
@@ -358,27 +312,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
|
|
break;
|
|
}
|
|
|
|
- atomic = !iov_fault_in_pages_write(iov, chars);
|
|
-redo:
|
|
- if (atomic)
|
|
- addr = kmap_atomic(buf->page);
|
|
- else
|
|
- addr = kmap(buf->page);
|
|
- error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic);
|
|
- if (atomic)
|
|
- kunmap_atomic(addr);
|
|
- else
|
|
- kunmap(buf->page);
|
|
- if (unlikely(error)) {
|
|
- /*
|
|
- * Just retry with the slow path if we failed.
|
|
- */
|
|
- if (atomic) {
|
|
- atomic = 0;
|
|
- goto redo;
|
|
- }
|
|
+ written = copy_page_to_iter(buf->page, buf->offset, chars, &iter);
|
|
+ if (unlikely(written < chars)) {
|
|
if (!ret)
|
|
- ret = error;
|
|
+ ret = -EFAULT;
|
|
break;
|
|
}
|
|
ret += chars;
|
|
--
|
|
cgit v1.1
|
|
|