[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