This duplicates the optimization in file_read_actor as a later patch
will replace it with a call to __iov_iter_copy_to_user().

Signed-off-by: Dave Kleikamp <dave.kleik...@oracle.com>
---
 fs/iov-iter.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/fs/iov-iter.c b/fs/iov-iter.c
index 6cb6be0..59f9556 100644
--- a/fs/iov-iter.c
+++ b/fs/iov-iter.c
@@ -80,17 +80,32 @@ static size_t ii_iovec_copy_to_user(struct page *page,
                        return 0;
        }
 
-       kaddr = kmap(page);
        if (likely(i->nr_segs == 1)) {
                int left;
                char __user *buf = iov->iov_base + i->iov_offset;
+               /*
+                * Faults on the destination of a read are common, so do it
+                * before taking the kmap.
+                */
+               if (!fault_in_pages_writeable(buf, bytes)) {
+                       kaddr = kmap_atomic(page);
+                       left = __copy_to_user_inatomic(buf, kaddr + offset,
+                                                    bytes);
+                       kunmap_atomic(kaddr);
+                       if (left == 0)
+                               goto success;
+               }
+               kaddr = kmap(page);
                left = copy_to_user(buf, kaddr + offset, bytes);
+               kunmap(page);
+success:
                copied = bytes - left;
        } else {
+               kaddr = kmap(page);
                copied = __iovec_copy_to_user(kaddr + offset, iov,
                                              i->iov_offset, bytes, 0);
+               kunmap(page);
        }
-       kunmap(page);
        return copied;
 }
 
-- 
1.8.1.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to