Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
[firefly-linux-kernel-4.4.55.git] / fs / pipe.c
index 6679c95eb4c3216f427451e6344dbde3ae07c628..034bffac3f9724c6121f4635ba9740d61e106d06 100644 (file)
--- 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;