diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-09-17 18:02:44 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-09-27 18:12:24 -0400 |
commit | 4bce9f6ee8f84fdf333d0fd7fcf7f0d8c7cce7fa (patch) | |
tree | a5d3f51f67b05e37d3de3ed9201794924b66efc2 | |
parent | 08895a8b6b06ed2323cd97a36ee40a116b3db8ed (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.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 | ||||
-rw-r--r-- | fs/ntfs/file.c | 2 | ||||
-rw-r--r-- | include/linux/pagemap.h | 54 | ||||
-rw-r--r-- | include/linux/uio.h | 1 | ||||
-rw-r--r-- | lib/iov_iter.c | 3 |
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); | |||
518 | extern void add_page_wait_queue(struct page *page, wait_queue_t *waiter); | 518 | extern 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 | */ |
525 | static inline int fault_in_pages_writeable(char __user *uaddr, int size) | 523 | static 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 | |||
545 | static 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 | */ | ||
572 | static 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 | ||
599 | static inline int fault_in_multipages_readable(const char __user *uaddr, | 550 | static 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); |
77 | void iov_iter_advance(struct iov_iter *i, size_t bytes); | 77 | void iov_iter_advance(struct iov_iter *i, size_t bytes); |
78 | int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes); | 78 | int 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 | ||
80 | size_t iov_iter_single_seg_count(const struct iov_iter *i); | 79 | size_t iov_iter_single_seg_count(const struct iov_iter *i); |
81 | size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, | 80 | size_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;})) |