2008-10-06 15:10:21

by Gregory Haskins

[permalink] [raw]
Subject: [RT PATCH v3 0/2] Fix for "[BUG][PPC64] BUG in 2.6.26.5-rt9 causing Hang"

Hi Steve,
Chirag reported (via IRC) that v2 fixed his issue. V3 is identical to v2
except I cleaned up the patch description and fixed a comment typo. This
applies to 26.5-rt9. Please consider it an urgent fix for -rt10.

Regards,
-Greg

---

Gregory Haskins (2):
RT: fix push_rt_task() to handle dequeue_pushable properly
RT: Remove comment that is no longer true


kernel/sched_rt.c | 44 ++++++++++++++++++++++----------------------
1 files changed, 22 insertions(+), 22 deletions(-)

--


2008-10-06 15:10:40

by Gregory Haskins

[permalink] [raw]
Subject: [RT PATCH v3 1/2] RT: Remove comment that is no longer true

We fixed the condition noted in the comment with the "pushable_tasks"
logic, but forgot to remove this comment. Lets clean it up.

Signed-off-by: Gregory Haskins <[email protected]>
---

kernel/sched_rt.c | 10 ----------
1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 57a0c0d..59ead84 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1125,16 +1125,6 @@ out:
return 1;
}

-/*
- * TODO: Currently we just use the second highest prio task on
- * the queue, and stop when it can't migrate (or there's
- * no more RT tasks). There may be a case where a lower
- * priority RT task has a different affinity than the
- * higher RT task. In this case the lower RT task could
- * possibly be able to migrate where as the higher priority
- * RT task could not. We currently ignore this issue.
- * Enhancements are welcome!
- */
static void push_rt_tasks(struct rq *rq)
{
/* push_rt_task will return true if it moved an RT */

2008-10-06 15:11:17

by Gregory Haskins

[permalink] [raw]
Subject: [RT PATCH v3 2/2] RT: fix push_rt_task() to handle dequeue_pushable properly

A panic was discovered by Chirag Jog where a BUG_ON sanity check
in the new "pushable_task" logic would trigger a panic under
certain circumstances:

http://lkml.org/lkml/2008/9/25/189

Gilles Carry discovered that the root cause was attributed to the
pushable_tasks list getting corrupted in the push_rt_task logic.
This was the result of a dropped rq lock in double_lock_balance
allowing a task in the process of being pushed to potentially migrate
away, and thus corrupt the pushable_tasks() list.

I traced back the problem as introduced by the pushable_tasks patch
that went in recently. There is a "retry" path in push_rt_task()
that actually had a compound conditional to decide whether to
retry or exit. I missed the meaning behind the rationale for the
virtual "if(!task) goto out;" portion of the compound statement and
thus did not handle it properly. The new pushable_tasks logic
actually creates three distinct conditions:

1) an untouched and unpushable task should be dequeued
2) a migrated task where more pushable tasks remain should be retried
3) a migrated task where no more pushable tasks exist should exit

The original logic mushed (1) and (3) together, resulting in the
system dequeuing a migrated task (against an unlocked foreign run-queue
nonetheless).

To fix this, we get rid of the notion of "paranoid" and we support the
three unique conditions properly. The paranoid feature is no longer
relevant with the new pushable logic (since pushable naturally limits
the loop) anyway, so lets just remove it.

Reported-By: Chirag Jog <[email protected]>
Found-by: Gilles Carry <[email protected]>
Signed-off-by: Gregory Haskins <[email protected]>
---

kernel/sched_rt.c | 34 ++++++++++++++++++++++------------
1 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 59ead84..05a1d4a 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1056,7 +1056,6 @@ static int push_rt_task(struct rq *rq)
{
struct task_struct *next_task;
struct rq *lowest_rq;
- int paranoid = RT_MAX_TRIES;

if (!rq->rt.overloaded)
return 0;
@@ -1090,23 +1089,34 @@ static int push_rt_task(struct rq *rq)
struct task_struct *task;
/*
* find lock_lowest_rq releases rq->lock
- * so it is possible that next_task has changed.
- * If it has, then try again.
+ * so it is possible that next_task has migrated.
+ *
+ * We need to make sure that the task is still on the same
+ * run-queue and is also still the next task eligible for
+ * pushing.
*/
task = pick_next_pushable_task(rq);
- if (unlikely(task != next_task) && task && paranoid--) {
- put_task_struct(next_task);
- next_task = task;
- goto retry;
+ if (task_cpu(next_task) == rq->cpu && task == next_task) {
+ /*
+ * If we get here, the task hasnt moved at all, but
+ * it has failed to push. We will not try again,
+ * since the other cpus will pull from us when they
+ * are ready.
+ */
+ dequeue_pushable_task(rq, next_task);
+ goto out;
}
+
+ if (!task)
+ /* No more tasks, just exit */
+ goto out;

/*
- * Once we have failed to push this task, we will not
- * try again, since the other cpus will pull from us
- * when they are ready
+ * Something has shifted, try again.
*/
- dequeue_pushable_task(rq, next_task);
- goto out;
+ put_task_struct(next_task);
+ next_task = task;
+ goto retry;
}

deactivate_task(rq, next_task, 0);

2008-10-07 06:08:19

by Gilles Carry

[permalink] [raw]
Subject: Re: [RT PATCH v3 0/2] Fix for "[BUG][PPC64] BUG in 2.6.26.5-rt9 causing Hang"


Gregory Haskins wrote:
> Hi Steve,
> Chirag reported (via IRC) that v2 fixed his issue. V3 is identical to v2
> except I cleaned up the patch description and fixed a comment typo. This
> applies to 26.5-rt9. Please consider it an urgent fix for -rt10.
>

Hi,

After 24 hours of testing on PPC64, I confirm that this patch fixes the issue.

Gilles.