diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-03-02 05:00:57 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-02 05:06:49 -0500 |
commit | f180053694b43d5714bf56cb95499a3c32ff155c (patch) | |
tree | 00286fcc88d2842629b039da4009a1332b3a1719 /mm | |
parent | 34754b69a6f87aa6aa2860525a82f12532f83afd (diff) |
x86, mm: dont use non-temporal stores in pagecache accesses
Impact: standardize IO on cached ops
On modern CPUs it is almost always a bad idea to use non-temporal stores,
as the regression in this commit has shown it:
30d697f: x86: fix performance regression in write() syscall
The kernel simply has no good information about whether using non-temporal
stores is a good idea or not - and trying to add heuristics only increases
complexity and inserts fragility.
The regression on cached write()s took very long to be found - over two
years. So dont take any chances and let the hardware decide how it makes
use of its caches.
The only exception is drivers/gpu/drm/i915/i915_gem.c: there were we are
absolutely sure that another entity (the GPU) will pick up the dirty
data immediately and that the CPU will not touch that data before the
GPU will.
Also, keep the _nocache() primitives to make it easier for people to
experiment with these details. There may be more clear-cut cases where
non-cached copies can be used, outside of filemap.c.
Cc: Salman Qazi <sqazi@google.com>
Cc: Nick Piggin <npiggin@suse.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/filemap.c | 11 | ||||
-rw-r--r-- | mm/filemap_xip.c | 2 |
2 files changed, 5 insertions, 8 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 60fd56772cc6..126d3973b3d1 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1816,14 +1816,14 @@ EXPORT_SYMBOL(file_remove_suid); | |||
1816 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, | 1816 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, |
1817 | const struct iovec *iov, size_t base, size_t bytes) | 1817 | const struct iovec *iov, size_t base, size_t bytes) |
1818 | { | 1818 | { |
1819 | size_t copied = 0, left = 0, total = bytes; | 1819 | size_t copied = 0, left = 0; |
1820 | 1820 | ||
1821 | while (bytes) { | 1821 | while (bytes) { |
1822 | char __user *buf = iov->iov_base + base; | 1822 | char __user *buf = iov->iov_base + base; |
1823 | int copy = min(bytes, iov->iov_len - base); | 1823 | int copy = min(bytes, iov->iov_len - base); |
1824 | 1824 | ||
1825 | base = 0; | 1825 | base = 0; |
1826 | left = __copy_from_user_inatomic_nocache(vaddr, buf, copy, total); | 1826 | left = __copy_from_user_inatomic(vaddr, buf, copy); |
1827 | copied += copy; | 1827 | copied += copy; |
1828 | bytes -= copy; | 1828 | bytes -= copy; |
1829 | vaddr += copy; | 1829 | vaddr += copy; |
@@ -1851,9 +1851,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, | |||
1851 | if (likely(i->nr_segs == 1)) { | 1851 | if (likely(i->nr_segs == 1)) { |
1852 | int left; | 1852 | int left; |
1853 | char __user *buf = i->iov->iov_base + i->iov_offset; | 1853 | char __user *buf = i->iov->iov_base + i->iov_offset; |
1854 | 1854 | left = __copy_from_user_inatomic(kaddr + offset, buf, bytes); | |
1855 | left = __copy_from_user_inatomic_nocache(kaddr + offset, | ||
1856 | buf, bytes, bytes); | ||
1857 | copied = bytes - left; | 1855 | copied = bytes - left; |
1858 | } else { | 1856 | } else { |
1859 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, | 1857 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, |
@@ -1881,8 +1879,7 @@ size_t iov_iter_copy_from_user(struct page *page, | |||
1881 | if (likely(i->nr_segs == 1)) { | 1879 | if (likely(i->nr_segs == 1)) { |
1882 | int left; | 1880 | int left; |
1883 | char __user *buf = i->iov->iov_base + i->iov_offset; | 1881 | char __user *buf = i->iov->iov_base + i->iov_offset; |
1884 | 1882 | left = __copy_from_user(kaddr + offset, buf, bytes); | |
1885 | left = __copy_from_user_nocache(kaddr + offset, buf, bytes, bytes); | ||
1886 | copied = bytes - left; | 1883 | copied = bytes - left; |
1887 | } else { | 1884 | } else { |
1888 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, | 1885 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, |
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index bf54f8a2cf1d..0c04615651b7 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c | |||
@@ -354,7 +354,7 @@ __xip_file_write(struct file *filp, const char __user *buf, | |||
354 | break; | 354 | break; |
355 | 355 | ||
356 | copied = bytes - | 356 | copied = bytes - |
357 | __copy_from_user_nocache(xip_mem + offset, buf, bytes, bytes); | 357 | __copy_from_user_nocache(xip_mem + offset, buf, bytes); |
358 | 358 | ||
359 | if (likely(copied > 0)) { | 359 | if (likely(copied > 0)) { |
360 | status = copied; | 360 | status = copied; |