From: Måns Rullgård <mru@inprovide.com>

Teach sysrq-N to switch all rt-policy tasks to SCHED_OTHER.  For recovering
from (and diagnosing) userspace bugs.

Acked-by: Ingo Molnar <mingo@elte.hu>

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/char/sysrq.c  |   12 +++++++++++-
 25-akpm/include/linux/sched.h |    6 ++++++
 25-akpm/kernel/sched.c        |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+), 1 deletion(-)

diff -puN drivers/char/sysrq.c~sysrq-n-changes-rt-tasks-to-normal drivers/char/sysrq.c
--- 25/drivers/char/sysrq.c~sysrq-n-changes-rt-tasks-to-normal	Mon Nov  1 14:40:17 2004
+++ 25-akpm/drivers/char/sysrq.c	Mon Nov  1 14:40:17 2004
@@ -247,6 +247,16 @@ static struct sysrq_key_op sysrq_kill_op
 
 /* END SIGNAL SYSRQ HANDLERS BLOCK */
 
+static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
+			      struct tty_struct *tty)
+{
+	normalize_rt_tasks();
+}
+static struct sysrq_key_op sysrq_unrt_op = {
+	.handler	= sysrq_handle_unrt,
+	.help_msg	= "Nice",
+	.action_msg	= "Nice All RT Tasks"
+};
 
 /* Key Operations table and lock */
 static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED;
@@ -281,7 +291,7 @@ static struct sysrq_key_op *sysrq_key_ta
 #endif
 /* l */	NULL,
 /* m */	&sysrq_showmem_op,
-/* n */	NULL,
+/* n */	&sysrq_unrt_op,
 /* o */	NULL, /* This will often be registered
 		 as 'Off' at init time */
 /* p */	&sysrq_showregs_op,
diff -puN include/linux/sched.h~sysrq-n-changes-rt-tasks-to-normal include/linux/sched.h
--- 25/include/linux/sched.h~sysrq-n-changes-rt-tasks-to-normal	Mon Nov  1 14:40:17 2004
+++ 25-akpm/include/linux/sched.h	Mon Nov  1 14:40:17 2004
@@ -1125,6 +1125,12 @@ static inline void arch_pick_mmap_layout
 extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
 extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
 
+#ifdef CONFIG_MAGIC_SYSRQ
+
+extern void normalize_rt_tasks(void);
+
+#endif
+
 #endif /* __KERNEL__ */
 
 extern void init_sched_domain_sysctl(void);
diff -puN kernel/sched.c~sysrq-n-changes-rt-tasks-to-normal kernel/sched.c
--- 25/kernel/sched.c~sysrq-n-changes-rt-tasks-to-normal	Mon Nov  1 14:40:17 2004
+++ 25-akpm/kernel/sched.c	Mon Nov  1 14:40:17 2004
@@ -4868,3 +4868,35 @@ void destroy_sched_domain_sysctl()
 {
 }
 #endif
+
+#ifdef CONFIG_MAGIC_SYSRQ
+void normalize_rt_tasks(void)
+{
+       struct task_struct *p;
+       prio_array_t *array;
+       unsigned long flags;
+       runqueue_t *rq;
+
+       read_lock_irq(&tasklist_lock);
+       for_each_process (p) {
+               if (!rt_task(p))
+                       continue;
+
+               rq = task_rq_lock(p, &flags);
+
+               array = p->array;
+               if (array)
+                       deactivate_task(p, task_rq(p));
+               __setscheduler(p, SCHED_NORMAL, 0);
+               if (array) {
+                       __activate_task(p, task_rq(p));
+                       resched_task(rq->curr);
+               }
+
+               task_rq_unlock(rq, &flags);
+       }
+       read_unlock_irq(&tasklist_lock);
+}
+
+EXPORT_SYMBOL(normalize_rt_tasks);
+#endif /* CONFIG_MAGIC_SYSRQ */
_