[S390] don't call handle_mm_fault() if in an atomic context.
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Tue, 9 Jan 2007 09:18:50 +0000 (10:18 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 9 Jan 2007 09:18:50 +0000 (10:18 +0100)
There are several places in the futex code where a spin_lock is held
and still uaccesses happen. Deadlocks are avoided by increasing the
preempt count. The pagefault handler will then not take any locks
but will immediately search the fixup tables.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/lib/uaccess_pt.c
arch/s390/lib/uaccess_std.c
include/asm-s390/futex.h

index 633249c3ba9180ea2aa75534b0b64458a6825191..49c3e46b406573011d591bbcbd36e6825deb0578 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/futex.h>
@@ -18,6 +19,8 @@ static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
        struct vm_area_struct *vma;
        int ret = -EFAULT;
 
+       if (in_atomic())
+               return ret;
        down_read(&mm->mmap_sem);
        vma = find_vma(mm, address);
        if (unlikely(!vma))
index bbaca66fa29356af1b0c7ea5589622f28aec4519..56a0214e9928c371c6cce379e599aaf0f61ef8cd 100644 (file)
@@ -258,8 +258,6 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
 {
        int oldval = 0, newval, ret;
 
-       pagefault_disable();
-
        switch (op) {
        case FUTEX_OP_SET:
                __futex_atomic_op("lr %2,%5\n",
@@ -284,7 +282,6 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
        default:
                ret = -ENOSYS;
        }
-       pagefault_enable();
        *old = oldval;
        return ret;
 }
index 5e261e1de6719bb99a638421e63eec8c02e5f79a..5c5d02de49e9ae53fe5728fef181f1657fd4c3dc 100644 (file)
@@ -4,8 +4,8 @@
 #ifdef __KERNEL__
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/uaccess.h>
 
 static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 {
@@ -21,7 +21,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
        if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
                return -EFAULT;
 
+       pagefault_disable();
        ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval);
+       pagefault_enable();
 
        if (!ret) {
                switch (cmp) {