The patch titled

     s390: pfault interrupt race

has been added to the -mm tree.  Its filename is

     s390-pfault-interrupt-race.patch

Patches currently in -mm which might be from [EMAIL PROTECTED] are

s390-machine-check-handler-bugs.patch
s390-debug-feature-changes.patch
s390-deadlock-in-dasd_devmap.patch
s390-64-bit-diag250-support.patch
s390-reipl-fix-and-extern-static-inline.patch
s390-pfault-interrupt-race.patch
s390-crypto-driver-update.patch
s390-compat-system-calls.patch
s390-spinlock-corner-case.patch
s390-disconnected-3270-console.patch



From: Martin Schwidefsky <[EMAIL PROTECTED]>

There is a race in pfault_interrupt.  That function gets called two times for
each pfault notification.  Once with a subcode of 0 to indicate that a real
page is not available and once with a subcode of 0x80 to indicate that the
page is present again.

Since the two external interrupts can be delivered on two different cpus the
order in which the two calls are made is unpredictable.  It is possible that
the subcode 0x80 interrupt is completed before the subcode 0x00 interrupt has
done the wake_up() call.

To avoid calling wake_up() on an already removed task structure proper task
structure reference counting is needed.  Increase the reference counter in the
subcode 0x00 interrupt before setting pfault_wait to zero and return the
reference after the wake_up call.

Signed-off-by: Martin Schwidefsky <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
---

 arch/s390/mm/fault.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletion(-)

diff -puN arch/s390/mm/fault.c~s390-pfault-interrupt-race arch/s390/mm/fault.c
--- devel/arch/s390/mm/fault.c~s390-pfault-interrupt-race       2005-08-29 
23:58:31.000000000 -0700
+++ devel-akpm/arch/s390/mm/fault.c     2005-08-29 23:58:31.000000000 -0700
@@ -563,12 +563,14 @@ pfault_interrupt(struct pt_regs *regs, _
                         * interrupt. pfault_wait is valid. Set pfault_wait
                         * back to zero and wake up the process. This can
                         * safely be done because the task is still sleeping
-                        * and can't procude new pfaults. */
+                        * and can't produce new pfaults. */
                        tsk->thread.pfault_wait = 0;
                        wake_up_process(tsk);
+                       put_task_struct(tsk);
                }
        } else {
                /* signal bit not set -> a real page is missing. */
+               get_task_struct(tsk);
                set_task_state(tsk, TASK_UNINTERRUPTIBLE);
                if (xchg(&tsk->thread.pfault_wait, 1) != 0) {
                        /* Completion interrupt was faster than the initial
@@ -578,6 +580,7 @@ pfault_interrupt(struct pt_regs *regs, _
                         * mode and can't produce new pfaults. */
                        tsk->thread.pfault_wait = 0;
                        set_task_state(tsk, TASK_RUNNING);
+                       put_task_struct(tsk);
                } else
                        set_tsk_need_resched(tsk);
        }
_
-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to