aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-09-17 18:02:44 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2016-09-27 18:12:24 -0400
commit4bce9f6ee8f84fdf333d0fd7fcf7f0d8c7cce7fa (patch)
treea5d3f51f67b05e37d3de3ed9201794924b66efc2
parent08895a8b6b06ed2323cd97a36ee40a116b3db8ed (diff)
get rid of separate multipage fault-in primitives
* the only remaining callers of "short" fault-ins are just as happy with generic variants (both in lib/iov_iter.c); switch them to multipage variants, kill the "short" ones * rename the multipage variants to now available plain ones. * get rid of compat macro defining iov_iter_fault_in_multipage_readable by expanding it in its only user. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--drivers/gpu/drm/armada/armada_gem.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c6
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c2
-rw-r--r--fs/ntfs/file.c2
-rw-r--r--include/linux/pagemap.h54
-rw-r--r--include/linux/uio.h1
-rw-r--r--lib/iov_iter.c3
7 files changed, 9 insertions, 61 deletions
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index cb8f0347b934..ff843160c600 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -387,7 +387,7 @@ int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data,
387 if (!access_ok(VERIFY_READ, ptr, args->size)) 387 if (!access_ok(VERIFY_READ, ptr, args->size))
388 return -EFAULT; 388 return -EFAULT;
389 389
390 ret = fault_in_multipages_readable(ptr, args->size); 390 ret = fault_in_pages_readable(ptr, args->size);
391 if (ret) 391 if (ret)
392 return ret; 392 return ret;
393 393
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a77ce9983f69..ccf56c60e6e8 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -675,7 +675,7 @@ i915_gem_gtt_pread(struct drm_device *dev,
675 675
676 mutex_unlock(&dev->struct_mutex); 676 mutex_unlock(&dev->struct_mutex);
677 if (likely(!i915.prefault_disable)) { 677 if (likely(!i915.prefault_disable)) {
678 ret = fault_in_multipages_writeable(user_data, remain); 678 ret = fault_in_pages_writeable(user_data, remain);
679 if (ret) { 679 if (ret) {
680 mutex_lock(&dev->struct_mutex); 680 mutex_lock(&dev->struct_mutex);
681 goto out_unpin; 681 goto out_unpin;
@@ -803,7 +803,7 @@ i915_gem_shmem_pread(struct drm_device *dev,
803 mutex_unlock(&dev->struct_mutex); 803 mutex_unlock(&dev->struct_mutex);
804 804
805 if (likely(!i915.prefault_disable) && !prefaulted) { 805 if (likely(!i915.prefault_disable) && !prefaulted) {
806 ret = fault_in_multipages_writeable(user_data, remain); 806 ret = fault_in_pages_writeable(user_data, remain);
807 /* Userspace is tricking us, but we've already clobbered 807 /* Userspace is tricking us, but we've already clobbered
808 * its pages with the prefault and promised to write the 808 * its pages with the prefault and promised to write the
809 * data up to the first fault. Hence ignore any errors 809 * data up to the first fault. Hence ignore any errors
@@ -1267,7 +1267,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
1267 return -EFAULT; 1267 return -EFAULT;
1268 1268
1269 if (likely(!i915.prefault_disable)) { 1269 if (likely(!i915.prefault_disable)) {
1270 ret = fault_in_multipages_readable(u64_to_user_ptr(args->data_ptr), 1270 ret = fault_in_pages_readable(u64_to_user_ptr(args->data_ptr),
1271 args->size); 1271 args->size);
1272 if (ret) 1272 if (ret)
1273 return -EFAULT; 1273 return -EFAULT;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index b35e5b6475b2..72628edda376 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1048,7 +1048,7 @@ validate_exec_list(struct drm_device *dev,
1048 return -EFAULT; 1048 return -EFAULT;
1049 1049
1050 if (likely(!i915.prefault_disable)) { 1050 if (likely(!i915.prefault_disable)) {
1051 if (fault_in_multipages_readable(ptr, length)) 1051 if (fault_in_pages_readable(ptr, length))
1052 return -EFAULT; 1052 return -EFAULT;
1053 } 1053 }
1054 } 1054 }
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index f548629dfaac..bf72a2c58b75 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -1850,7 +1850,7 @@ again:
1850 * pages being swapped out between us bringing them into memory 1850 * pages being swapped out between us bringing them into memory
1851 * and doing the actual copying. 1851 * and doing the actual copying.
1852 */ 1852 */
1853 if (unlikely(iov_iter_fault_in_multipages_readable(i, bytes))) { 1853 if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
1854 status = -EFAULT; 1854 status = -EFAULT;
1855 break; 1855 break;
1856 } 1856 }
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 01e84436cddf..cb2e1d06d2e9 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -518,59 +518,10 @@ void page_endio(struct page *page, bool is_write, int err);
518extern void add_page_wait_queue(struct page *page, wait_queue_t *waiter); 518extern void add_page_wait_queue(struct page *page, wait_queue_t *waiter);
519 519
520/* 520/*
521 * Fault one or two userspace pages into pagetables. 521 * Fault everything in given userspace address range in.
522 * Return -EINVAL if more than two pages would be needed.
523 * Return non-zero on a fault.
524 */ 522 */
525static inline int fault_in_pages_writeable(char __user *uaddr, int size) 523static inline int fault_in_pages_writeable(char __user *uaddr, int size)
526{ 524{
527 int span, ret;
528
529 if (unlikely(size == 0))
530 return 0;
531
532 span = offset_in_page(uaddr) + size;
533 if (span > 2 * PAGE_SIZE)
534 return -EINVAL;
535 /*
536 * Writing zeroes into userspace here is OK, because we know that if
537 * the zero gets there, we'll be overwriting it.
538 */
539 ret = __put_user(0, uaddr);
540 if (ret == 0 && span > PAGE_SIZE)
541 ret = __put_user(0, uaddr + size - 1);
542 return ret;
543}
544
545static inline int fault_in_pages_readable(const char __user *uaddr, int size)
546{
547 volatile char c;
548 int ret;
549
550 if (unlikely(size == 0))
551 return 0;
552
553 ret = __get_user(c, uaddr);
554 if (ret == 0) {
555 const char __user *end = uaddr + size - 1;
556
557 if (((unsigned long)uaddr & PAGE_MASK) !=
558 ((unsigned long)end & PAGE_MASK)) {
559 ret = __get_user(c, end);
560 (void)c;
561 }
562 }
563 return ret;
564}
565
566/*
567 * Multipage variants of the above prefault helpers, useful if more than
568 * PAGE_SIZE of data needs to be prefaulted. These are separate from the above
569 * functions (which only handle up to PAGE_SIZE) to avoid clobbering the
570 * filemap.c hotpaths.
571 */
572static inline int fault_in_multipages_writeable(char __user *uaddr, int size)
573{
574 char __user *end = uaddr + size - 1; 525 char __user *end = uaddr + size - 1;
575 526
576 if (unlikely(size == 0)) 527 if (unlikely(size == 0))
@@ -596,8 +547,7 @@ static inline int fault_in_multipages_writeable(char __user *uaddr, int size)
596 return 0; 547 return 0;
597} 548}
598 549
599static inline int fault_in_multipages_readable(const char __user *uaddr, 550static inline int fault_in_pages_readable(const char __user *uaddr, int size)
600 int size)
601{ 551{
602 volatile char c; 552 volatile char c;
603 const char __user *end = uaddr + size - 1; 553 const char __user *end = uaddr + size - 1;
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 75b4aaf31a9d..7709f8d4a9cb 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -76,7 +76,6 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
76 struct iov_iter *i, unsigned long offset, size_t bytes); 76 struct iov_iter *i, unsigned long offset, size_t bytes);
77void iov_iter_advance(struct iov_iter *i, size_t bytes); 77void iov_iter_advance(struct iov_iter *i, size_t bytes);
78int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes); 78int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
79#define iov_iter_fault_in_multipages_readable iov_iter_fault_in_readable
80size_t iov_iter_single_seg_count(const struct iov_iter *i); 79size_t iov_iter_single_seg_count(const struct iov_iter *i);
81size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, 80size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
82 struct iov_iter *i); 81 struct iov_iter *i);
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 7e3138cfc8c9..ce4632002611 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -306,8 +306,7 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
306 306
307 if (!(i->type & (ITER_BVEC|ITER_KVEC))) { 307 if (!(i->type & (ITER_BVEC|ITER_KVEC))) {
308 iterate_iovec(i, bytes, v, iov, skip, ({ 308 iterate_iovec(i, bytes, v, iov, skip, ({
309 err = fault_in_multipages_readable(v.iov_base, 309 err = fault_in_pages_readable(v.iov_base, v.iov_len);
310 v.iov_len);
311 if (unlikely(err)) 310 if (unlikely(err))
312 return err; 311 return err;
313 0;})) 312 0;}))