[PATCH] ppc64: kill might_sleep() warnings in __copy_*_user_inatomic

Olof Johansson olof at austin.ibm.com
Fri Mar 11 10:39:32 EST 2005


On Thu, Mar 10, 2005 at 08:54:36PM +0100, Arnd Bergmann wrote:
> I currently get warnings from futex resulting from Olofs futex+rwsem fix
> combined with the fact that ppc64 __copy_from_user has a might_sleep
> check in it:
> 
> [ 9607.577071] Debug: sleeping function called from invalid context at include2/asm/uaccess.h:2
> 28
> [ 9607.676181] in_atomic():1, irqs_disabled():0
> [ 9607.724741] Call Trace:
> [ 9607.752058] [c00000000d68fab0] [c000000001f0fb80] 0xc000000001f0fb80 (unreliable)
> [ 9607.835030] [c00000000d68fb30] [c000000000042420] .__might_sleep+0xf8/0x108
> [ 9607.912936] [c00000000d68fbd0] [c00000000006ac34] .do_futex+0x224/0x858
> 
> The fix is to do the check only in copy_*_user, not __copy_*_user. This is the
> same that most other architectures do.

Actually, I think I would prefer the following. It renames current
__copy_{to,from}_user to __copy_{to,from}_user_inatomic, adds the
old ones as inlines doing the  might_sleep() and calling the inatomics
afterwards. This way the calls to __copy_{to,from}_user() will be caught
if called under lock or preemption as well. This is also how i386 does it.

This was coded up during travelling, so I haven't been able to boot
the patch, only build it. Dave Jones made me aware of it since he hit
exactly the above on ppc64 himself, but it was right before I left town.


-Olof


---

This implements the __copy_{to,from}_user_inatomic() functions on ppc64. The only
difference between the inatomic and regular version is that inatomic does not call
might_sleep() to detect possible faults while holding locks/elevated preempt counts.


Signed-off-by: Olof Johansson <olof at austin.ibm.com>


Index: linux-2.5/include/asm-ppc64/uaccess.h
===================================================================
--- linux-2.5.orig/include/asm-ppc64/uaccess.h	2005-03-09 17:17:31.000000000 -0600
+++ linux-2.5/include/asm-ppc64/uaccess.h	2005-03-09 17:21:01.000000000 -0600
@@ -223,9 +223,8 @@ extern unsigned long __copy_tofrom_user(
 					unsigned long size);
 
 static inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
+__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 {
-	might_sleep();
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
 
@@ -248,9 +247,15 @@ __copy_from_user(void *to, const void __
 }
 
 static inline unsigned long
-__copy_to_user(void __user *to, const void *from, unsigned long n)
+__copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	might_sleep();
+	return __copy_from_user_inatomic(to, from, n);
+}
+
+static inline unsigned long
+__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
+{
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
 
@@ -272,6 +277,13 @@ __copy_to_user(void __user *to, const vo
 	return __copy_tofrom_user(to, (__force const void __user *) from, n);
 }
 
+static inline unsigned long
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	might_sleep();
+	return __copy_to_user_inatomic(to, from, n);
+}
+
 #define __copy_in_user(to, from, size) \
 	__copy_tofrom_user((to), (from), (size))
 
@@ -284,9 +296,6 @@ extern unsigned long copy_in_user(void _
 
 extern unsigned long __clear_user(void __user *addr, unsigned long size);
 
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
 static inline unsigned long
 clear_user(void __user *addr, unsigned long size)
 {



More information about the Linuxppc64-dev mailing list