Kyle McMartin 8394f9a
From 799c10559d60f159ab2232203f222f18fa3c4a5f Mon Sep 17 00:00:00 2001
Kyle McMartin 8394f9a
From: Linus Torvalds <torvalds@linux-foundation.org>
Kyle McMartin 8394f9a
Date: Fri, 15 Oct 2010 11:09:28 -0700
Kyle McMartin 8394f9a
Subject: [PATCH] De-pessimize rds_page_copy_user
Kyle McMartin 8394f9a
Kyle McMartin 8394f9a
Don't try to "optimize" rds_page_copy_user() by using kmap_atomic() and
Kyle McMartin 8394f9a
the unsafe atomic user mode accessor functions.  It's actually slower
Kyle McMartin 8394f9a
than the straightforward code on any reasonable modern CPU.
Kyle McMartin 8394f9a
Kyle McMartin 8394f9a
Back when the code was written (although probably not by the time it was
Kyle McMartin 8394f9a
actually merged, though), 32-bit x86 may have been the dominant
Kyle McMartin 8394f9a
architecture.  And there kmap_atomic() can be a lot faster than kmap()
Kyle McMartin 8394f9a
(unless you have very good locality, in which case the virtual address
Kyle McMartin 8394f9a
caching by kmap() can overcome all the downsides).
Kyle McMartin 8394f9a
Kyle McMartin 8394f9a
But these days, x86-64 may not be more populous, but it's getting there
Kyle McMartin 8394f9a
(and if you care about performance, it's definitely already there -
Kyle McMartin 8394f9a
you'd have upgraded your CPU's already in the last few years).  And on
Kyle McMartin 8394f9a
x86-64, the non-kmap_atomic() version is faster, simply because the code
Kyle McMartin 8394f9a
is simpler and doesn't have the "re-try page fault" case.
Kyle McMartin 8394f9a
Kyle McMartin 8394f9a
People with old hardware are not likely to care about RDS anyway, and
Kyle McMartin 8394f9a
the optimization for the 32-bit case is simply buggy, since it doesn't
Kyle McMartin 8394f9a
verify the user addresses properly.
Kyle McMartin 8394f9a
Kyle McMartin 8394f9a
Reported-by: Dan Rosenberg <drosenberg@vsecurity.com>
Kyle McMartin 8394f9a
Acked-by: Andrew Morton <akpm@linux-foundation.org>
Kyle McMartin 8394f9a
Cc: stable@kernel.org
Kyle McMartin 8394f9a
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Kyle McMartin 8394f9a
---
Kyle McMartin 8394f9a
 net/rds/page.c |   27 +++++++--------------------
Kyle McMartin 8394f9a
 1 files changed, 7 insertions(+), 20 deletions(-)
Kyle McMartin 8394f9a
Kyle McMartin 8394f9a
diff --git a/net/rds/page.c b/net/rds/page.c
Kyle McMartin 8394f9a
index 595a952..1dfbfea 100644
Kyle McMartin 8394f9a
--- a/net/rds/page.c
Kyle McMartin 8394f9a
+++ b/net/rds/page.c
Kyle McMartin 8394f9a
@@ -57,30 +57,17 @@ int rds_page_copy_user(struct page *page, unsigned long offset,
Kyle McMartin 8394f9a
 	unsigned long ret;
Kyle McMartin 8394f9a
 	void *addr;
Kyle McMartin 8394f9a
 
Kyle McMartin 8394f9a
-	if (to_user)
Kyle McMartin 8394f9a
+	addr = kmap(page);
Kyle McMartin 8394f9a
+	if (to_user) {
Kyle McMartin 8394f9a
 		rds_stats_add(s_copy_to_user, bytes);
Kyle McMartin 8394f9a
-	else
Kyle McMartin 8394f9a
+		ret = copy_to_user(ptr, addr + offset, bytes);
Kyle McMartin 8394f9a
+	} else {
Kyle McMartin 8394f9a
 		rds_stats_add(s_copy_from_user, bytes);
Kyle McMartin 8394f9a
-
Kyle McMartin 8394f9a
-	addr = kmap_atomic(page, KM_USER0);
Kyle McMartin 8394f9a
-	if (to_user)
Kyle McMartin 8394f9a
-		ret = __copy_to_user_inatomic(ptr, addr + offset, bytes);
Kyle McMartin 8394f9a
-	else
Kyle McMartin 8394f9a
-		ret = __copy_from_user_inatomic(addr + offset, ptr, bytes);
Kyle McMartin 8394f9a
-	kunmap_atomic(addr, KM_USER0);
Kyle McMartin 8394f9a
-
Kyle McMartin 8394f9a
-	if (ret) {
Kyle McMartin 8394f9a
-		addr = kmap(page);
Kyle McMartin 8394f9a
-		if (to_user)
Kyle McMartin 8394f9a
-			ret = copy_to_user(ptr, addr + offset, bytes);
Kyle McMartin 8394f9a
-		else
Kyle McMartin 8394f9a
-			ret = copy_from_user(addr + offset, ptr, bytes);
Kyle McMartin 8394f9a
-		kunmap(page);
Kyle McMartin 8394f9a
-		if (ret)
Kyle McMartin 8394f9a
-			return -EFAULT;
Kyle McMartin 8394f9a
+		ret = copy_from_user(addr + offset, ptr, bytes);
Kyle McMartin 8394f9a
 	}
Kyle McMartin 8394f9a
+	kunmap(page);
Kyle McMartin 8394f9a
 
Kyle McMartin 8394f9a
-	return 0;
Kyle McMartin 8394f9a
+	return ret ? -EFAULT : 0;
Kyle McMartin 8394f9a
 }
Kyle McMartin 8394f9a
 EXPORT_SYMBOL_GPL(rds_page_copy_user);
Kyle McMartin 8394f9a
 
Kyle McMartin 8394f9a
-- 
Kyle McMartin 8394f9a
1.7.3.2
Kyle McMartin 8394f9a