2007-02-26 07:22:30

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 0/6] Freezer changes

Hi,

The following series of patches contains modifications of the task freezer that
harden it and prepare it to be used in the CPU hotplug.

Greetings,
Rafael


2007-02-26 07:21:13

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 4/6] Freezer: Remove PF_NOFREEZE from rcutorture thread

From: Paul E. McKenney <[email protected]>

Remove PF_NOFREEZE from the rcutorture thread, adding a try_to_freeze() call as
required.

Signed-off-by: Paul E. McKenney <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Pavel Machek <[email protected]>
---
kernel/rcutorture.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

Index: linux-2.6.20-mm2/kernel/rcutorture.c
===================================================================
--- linux-2.6.20-mm2.orig/kernel/rcutorture.c 2007-02-22 23:51:54.000000000 +0100
+++ linux-2.6.20-mm2/kernel/rcutorture.c 2007-02-22 23:55:12.000000000 +0100
@@ -46,6 +46,7 @@
#include <linux/byteorder/swabb.h>
#include <linux/stat.h>
#include <linux/srcu.h>
+#include <linux/freezer.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <[email protected]> and "
@@ -585,7 +586,6 @@ rcu_torture_writer(void *arg)

VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
set_user_nice(current, 19);
- current->flags |= PF_NOFREEZE;

do {
schedule_timeout_uninterruptible(1);
@@ -607,6 +607,7 @@ rcu_torture_writer(void *arg)
}
rcu_torture_current_version++;
oldbatch = cur_ops->completed();
+ try_to_freeze();
} while (!kthread_should_stop() && !fullstop);
VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
while (!kthread_should_stop())

2007-02-26 07:21:12

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 5/6] Freezer: Remove PF_NOFREEZE from bluetooth threads

From: Rafael J. Wysocki <[email protected]>

Remove PF_NOFREEZE from the bluetooth threads, adding try_to_freeze() calls as
required.

Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Pavel Machek <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
---
net/bluetooth/bnep/core.c | 6 ++++--
net/bluetooth/cmtp/core.c | 4 +++-
net/bluetooth/hidp/core.c | 4 +++-
net/bluetooth/rfcomm/core.c | 4 +++-
4 files changed, 13 insertions(+), 5 deletions(-)

Index: linux-2.6.20-mm2/net/bluetooth/bnep/core.c
===================================================================
--- linux-2.6.20-mm2.orig/net/bluetooth/bnep/core.c 2007-02-23 00:26:58.000000000 +0100
+++ linux-2.6.20-mm2/net/bluetooth/bnep/core.c 2007-02-23 00:30:47.000000000 +0100
@@ -39,6 +39,7 @@
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/net.h>
+#include <linux/freezer.h>
#include <net/sock.h>

#include <linux/socket.h>
@@ -473,11 +474,12 @@ static int bnep_session(void *arg)

daemonize("kbnepd %s", dev->name);
set_user_nice(current, -15);
- current->flags |= PF_NOFREEZE;

init_waitqueue_entry(&wait, current);
add_wait_queue(sk->sk_sleep, &wait);
while (!atomic_read(&s->killed)) {
+ try_to_freeze();
+
set_current_state(TASK_INTERRUPTIBLE);

// RX
Index: linux-2.6.20-mm2/net/bluetooth/cmtp/core.c
===================================================================
--- linux-2.6.20-mm2.orig/net/bluetooth/cmtp/core.c 2007-02-23 00:26:58.000000000 +0100
+++ linux-2.6.20-mm2/net/bluetooth/cmtp/core.c 2007-02-23 00:31:01.000000000 +0100
@@ -34,6 +34,7 @@
#include <linux/ioctl.h>
#include <linux/file.h>
#include <linux/init.h>
+#include <linux/freezer.h>
#include <net/sock.h>

#include <linux/isdn/capilli.h>
@@ -287,11 +288,12 @@ static int cmtp_session(void *arg)

daemonize("kcmtpd_ctr_%d", session->num);
set_user_nice(current, -15);
- current->flags |= PF_NOFREEZE;

init_waitqueue_entry(&wait, current);
add_wait_queue(sk->sk_sleep, &wait);
while (!atomic_read(&session->terminate)) {
+ try_to_freeze();
+
set_current_state(TASK_INTERRUPTIBLE);

if (sk->sk_state != BT_CONNECTED)
Index: linux-2.6.20-mm2/net/bluetooth/hidp/core.c
===================================================================
--- linux-2.6.20-mm2.orig/net/bluetooth/hidp/core.c 2007-02-23 00:26:58.000000000 +0100
+++ linux-2.6.20-mm2/net/bluetooth/hidp/core.c 2007-02-23 00:31:17.000000000 +0100
@@ -35,6 +35,7 @@
#include <linux/file.h>
#include <linux/init.h>
#include <linux/wait.h>
+#include <linux/freezer.h>
#include <net/sock.h>

#include <linux/input.h>
@@ -547,13 +548,14 @@ static int hidp_session(void *arg)

daemonize("khidpd_%04x%04x", vendor, product);
set_user_nice(current, -15);
- current->flags |= PF_NOFREEZE;

init_waitqueue_entry(&ctrl_wait, current);
init_waitqueue_entry(&intr_wait, current);
add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
add_wait_queue(intr_sk->sk_sleep, &intr_wait);
while (!atomic_read(&session->terminate)) {
+ try_to_freeze();
+
set_current_state(TASK_INTERRUPTIBLE);

if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)
Index: linux-2.6.20-mm2/net/bluetooth/rfcomm/core.c
===================================================================
--- linux-2.6.20-mm2.orig/net/bluetooth/rfcomm/core.c 2007-02-23 00:26:58.000000000 +0100
+++ linux-2.6.20-mm2/net/bluetooth/rfcomm/core.c 2007-02-23 00:31:43.000000000 +0100
@@ -37,6 +37,7 @@
#include <linux/device.h>
#include <linux/net.h>
#include <linux/mutex.h>
+#include <linux/freezer.h>

#include <net/sock.h>
#include <asm/uaccess.h>
@@ -1851,6 +1852,8 @@ static void rfcomm_worker(void)
BT_DBG("");

while (!atomic_read(&terminate)) {
+ try_to_freeze();
+
if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
/* No pending events. Let's sleep.
* Incoming connections and data will wake us up. */
@@ -1937,7 +1940,6 @@ static int rfcomm_run(void *unused)

daemonize("krfcommd");
set_user_nice(current, -10);
- current->flags |= PF_NOFREEZE;

BT_DBG("");


2007-02-26 07:21:46

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 2/6] Freezer: Fix memory ordering in refrigerator

From: Oleg Nesterov <[email protected]>

refrigerator() can miss a wakeup, "wait event" loop needs a proper memory
ordering.

Signed-off-by: Oleg Nesterov <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Pavel Machek <[email protected]>
---
kernel/power/process.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

Index: linux-2.6.20-mm2/kernel/power/process.c
===================================================================
--- linux-2.6.20-mm2.orig/kernel/power/process.c
+++ linux-2.6.20-mm2/kernel/power/process.c
@@ -47,8 +47,10 @@ void refrigerator(void)
recalc_sigpending(); /* We sent fake signal, clean it up */
spin_unlock_irq(&current->sighand->siglock);

- while (frozen(current)) {
- current->state = TASK_UNINTERRUPTIBLE;
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (!frozen(current))
+ break;
schedule();
}
pr_debug("%s left refrigerator\n", current->comm);

2007-02-26 07:21:46

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 6/6] Freezer: Add try_to_freeze calls to all kernel threads

From: Rafael J. Wysocki <[email protected]>

Add try_to_freeze() calls to the remaining kernel threads that do not call
try_to_freeze() already, although they set PF_NOFREEZE.

In the future we are going to replace PF_NOFREEZE with a set of flags that will
be set to indicate in which situations the task should not be frozen (for
example, there can be a task that should be frozen for the CPU hotplugging and
should not be frozen for the system suspend). For this reason every kernel
thread should be able to freeze itself (ie. call try_to_freeze()), so that it
can be frozen whenever necessary.

Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Pavel Machek <[email protected]>
---
arch/i386/kernel/apm.c | 2 ++
drivers/block/loop.c | 2 ++
drivers/char/apm-emulation.c | 3 +++
drivers/ieee1394/ieee1394_core.c | 3 +++
drivers/md/md.c | 2 ++
drivers/mmc/card/queue.c | 3 +++
drivers/mtd/mtd_blkdevs.c | 3 +++
drivers/scsi/libsas/sas_scsi_host.c | 3 +++
drivers/scsi/scsi_error.c | 3 +++
drivers/usb/storage/usb.c | 2 ++
kernel/softirq.c | 2 ++
kernel/softlockup.c | 2 ++
kernel/workqueue.c | 3 +--
13 files changed, 31 insertions(+), 2 deletions(-)

Index: linux-2.6.20-mm2/arch/i386/kernel/apm.c
===================================================================
--- linux-2.6.20-mm2.orig/arch/i386/kernel/apm.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/arch/i386/kernel/apm.c 2007-02-23 00:34:25.000000000 +0100
@@ -227,6 +227,7 @@
#include <linux/dmi.h>
#include <linux/suspend.h>
#include <linux/kthread.h>
+#include <linux/freezer.h>

#include <asm/system.h>
#include <asm/uaccess.h>
@@ -1402,6 +1403,7 @@ static void apm_mainloop(void)
add_wait_queue(&apm_waitqueue, &wait);
set_current_state(TASK_INTERRUPTIBLE);
for (;;) {
+ try_to_freeze();
schedule_timeout(APM_CHECK_TIMEOUT);
if (kthread_should_stop())
break;
Index: linux-2.6.20-mm2/drivers/md/md.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/md/md.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/md/md.c 2007-02-23 00:34:25.000000000 +0100
@@ -4513,6 +4513,8 @@ static int md_thread(void * arg)
|| kthread_should_stop(),
thread->timeout);

+ try_to_freeze();
+
clear_bit(THREAD_WAKEUP, &thread->flags);

thread->run(thread->mddev);
Index: linux-2.6.20-mm2/drivers/mmc/card/queue.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/mmc/card/queue.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/mmc/card/queue.c 2007-02-23 00:34:25.000000000 +0100
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/kthread.h>
+#include <linux/freezer.h>

#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -71,6 +72,8 @@ static int mmc_queue_thread(void *d)
do {
struct request *req = NULL;

+ try_to_freeze();
+
spin_lock_irq(q->queue_lock);
set_current_state(TASK_INTERRUPTIBLE);
if (!blk_queue_plugged(q))
Index: linux-2.6.20-mm2/drivers/mtd/mtd_blkdevs.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/mtd/mtd_blkdevs.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/mtd/mtd_blkdevs.c 2007-02-23 00:34:25.000000000 +0100
@@ -20,6 +20,7 @@
#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/mutex.h>
+#include <linux/freezer.h>
#include <asm/uaccess.h>

static LIST_HEAD(blktrans_majors);
@@ -113,6 +114,8 @@ static int mtd_blktrans_thread(void *arg
schedule();
remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait);

+ try_to_freeze();
+
spin_lock_irq(rq->queue_lock);

continue;
Index: linux-2.6.20-mm2/drivers/usb/storage/usb.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/usb/storage/usb.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/usb/storage/usb.c 2007-02-23 00:34:25.000000000 +0100
@@ -304,6 +304,8 @@ static int usb_stor_control_thread(void
current->flags |= PF_NOFREEZE;

for(;;) {
+ try_to_freeze();
+
US_DEBUGP("*** thread sleeping.\n");
if(down_interruptible(&us->sema))
break;
Index: linux-2.6.20-mm2/drivers/ieee1394/ieee1394_core.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/ieee1394/ieee1394_core.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/ieee1394/ieee1394_core.c 2007-02-23 00:34:25.000000000 +0100
@@ -35,6 +35,7 @@
#include <linux/kthread.h>
#include <linux/preempt.h>
#include <linux/time.h>
+#include <linux/freezer.h>

#include <asm/system.h>
#include <asm/byteorder.h>
@@ -1081,6 +1082,8 @@ static int hpsbpkt_thread(void *__hi)
complete_routine(complete_data);
}

+ try_to_freeze();
+
set_current_state(TASK_INTERRUPTIBLE);
if (!skb_peek(&hpsbpkt_queue))
schedule();
Index: linux-2.6.20-mm2/drivers/char/apm-emulation.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/char/apm-emulation.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/char/apm-emulation.c 2007-02-23 00:34:25.000000000 +0100
@@ -27,6 +27,7 @@
#include <linux/completion.h>
#include <linux/kthread.h>
#include <linux/delay.h>
+#include <linux/freezer.h>

#include <asm/system.h>

@@ -539,6 +540,8 @@ static int kapmd(void *arg)
apm_event_t event;
int ret;

+ try_to_freeze();
+
wait_event_interruptible(kapmd_wait,
!queue_empty(&kapmd_queue) || kthread_should_stop());

Index: linux-2.6.20-mm2/drivers/block/loop.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/block/loop.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/block/loop.c 2007-02-23 00:34:25.000000000 +0100
@@ -74,6 +74,7 @@
#include <linux/highmem.h>
#include <linux/gfp.h>
#include <linux/kthread.h>
+#include <linux/freezer.h>

#include <asm/uaccess.h>

@@ -580,6 +581,7 @@ static int loop_thread(void *data)
set_user_nice(current, -20);

while (!kthread_should_stop() || lo->lo_bio) {
+ try_to_freeze();

wait_event_interruptible(lo->lo_event,
lo->lo_bio || kthread_should_stop());
Index: linux-2.6.20-mm2/drivers/scsi/libsas/sas_scsi_host.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/scsi/libsas/sas_scsi_host.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/scsi/libsas/sas_scsi_host.c 2007-02-23 00:34:25.000000000 +0100
@@ -39,6 +39,7 @@
#include <linux/err.h>
#include <linux/blkdev.h>
#include <linux/scatterlist.h>
+#include <linux/freezer.h>

/* ---------- SCSI Host glue ---------- */

@@ -875,6 +876,8 @@ static int sas_queue_thread(void *_sas_h
complete(&queue_th_comp);

while (1) {
+ try_to_freeze();
+
down_interruptible(&core->queue_thread_sema);
sas_queue(sas_ha);
if (core->queue_thread_kill)
Index: linux-2.6.20-mm2/drivers/scsi/scsi_error.c
===================================================================
--- linux-2.6.20-mm2.orig/drivers/scsi/scsi_error.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/drivers/scsi/scsi_error.c 2007-02-23 00:34:25.000000000 +0100
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
+#include <linux/freezer.h>

#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -1536,6 +1537,8 @@ int scsi_error_handler(void *data)
*/
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
+ try_to_freeze();
+
if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
shost->host_failed != shost->host_busy) {
SCSI_LOG_ERROR_RECOVERY(1,
Index: linux-2.6.20-mm2/kernel/softlockup.c
===================================================================
--- linux-2.6.20-mm2.orig/kernel/softlockup.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/kernel/softlockup.c 2007-02-23 00:34:25.000000000 +0100
@@ -13,6 +13,7 @@
#include <linux/kthread.h>
#include <linux/notifier.h>
#include <linux/module.h>
+#include <linux/freezer.h>

static DEFINE_SPINLOCK(print_lock);

@@ -93,6 +94,7 @@ static int watchdog(void * __bind_cpu)
* debug-printout triggers in softlockup_tick().
*/
while (!kthread_should_stop()) {
+ try_to_freeze();
set_current_state(TASK_INTERRUPTIBLE);
touch_softlockup_watchdog();
schedule();
Index: linux-2.6.20-mm2/kernel/softirq.c
===================================================================
--- linux-2.6.20-mm2.orig/kernel/softirq.c 2007-02-22 23:48:52.000000000 +0100
+++ linux-2.6.20-mm2/kernel/softirq.c 2007-02-23 00:34:25.000000000 +0100
@@ -18,6 +18,7 @@
#include <linux/rcupdate.h>
#include <linux/smp.h>
#include <linux/tick.h>
+#include <linux/freezer.h>

#include <asm/irq.h>
/*
@@ -494,6 +495,7 @@ static int ksoftirqd(void * __bind_cpu)
set_current_state(TASK_INTERRUPTIBLE);

while (!kthread_should_stop()) {
+ try_to_freeze();
preempt_disable();
if (!local_softirq_pending()) {
preempt_enable_no_resched();

2007-02-26 07:22:20

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 1/6] Freezer: Read PF_BORROWED_MM in a nonracy way

From: Rafael J. Wysocki <[email protected]>

The reading of PF_BORROWED_MM in is_user_space() without task_lock() is racy.
Fix it.

Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Pavel Machek <[email protected]>
---
kernel/power/process.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

Index: linux-2.6.20-mm2/kernel/power/process.c
===================================================================
--- linux-2.6.20-mm2.orig/kernel/power/process.c
+++ linux-2.6.20-mm2/kernel/power/process.c
@@ -8,6 +8,7 @@

#undef DEBUG

+#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/suspend.h>
@@ -92,7 +93,12 @@ static void cancel_freezing(struct task_

static inline int is_user_space(struct task_struct *p)
{
- return p->mm && !(p->flags & PF_BORROWED_MM);
+ int ret;
+
+ task_lock(p);
+ ret = p->mm && !(p->flags & PF_BORROWED_MM);
+ task_unlock(p);
+ return ret;
}

static unsigned int try_to_freeze_tasks(int freeze_user_space)

2007-02-26 07:22:30

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 3/6] Freezer: Close theoretical race between refrigerator and thaw_tasks

From: Rafael J. Wysocki <[email protected]>

If the freezing of tasks fails and a task is preempted in refrigerator() before
calling frozen_process(), then thaw_tasks() may run before this task is frozen.
In that case the task will freeze and no one will thaw it.

To fix this race we can call freezing(current) in refrigerator() along with
frozen_process(current) under the task_lock() which also should be taken in
the error path of try_to_freeze_tasks() as well as in thaw_process(). Moreover,
if thaw_process() additionally clears TIF_FREEZE for tasks that are not frozen,
we can be sure that all tasks are thawed and there are no pending "freeze"
requests after thaw_tasks() has run.

Signed-off-by: Rafael J. Wysocki <[email protected]>
---
include/linux/freezer.h | 4 ++++
kernel/power/process.c | 12 +++++++++++-
2 files changed, 15 insertions(+), 1 deletion(-)

Index: linux-2.6.20-mm2/include/linux/freezer.h
===================================================================
--- linux-2.6.20-mm2.orig/include/linux/freezer.h
+++ linux-2.6.20-mm2/include/linux/freezer.h
@@ -40,11 +40,15 @@ static inline void do_not_freeze(struct
*/
static inline int thaw_process(struct task_struct *p)
{
+ task_lock(p);
if (frozen(p)) {
p->flags &= ~PF_FROZEN;
+ task_unlock(p);
wake_up_process(p);
return 1;
}
+ clear_tsk_thread_flag(p, TIF_FREEZE);
+ task_unlock(p);
return 0;
}

Index: linux-2.6.20-mm2/kernel/power/process.c
===================================================================
--- linux-2.6.20-mm2.orig/kernel/power/process.c
+++ linux-2.6.20-mm2/kernel/power/process.c
@@ -39,10 +39,18 @@ void refrigerator(void)
/* Hmm, should we be allowed to suspend when there are realtime
processes around? */
long save;
+
+ task_lock(current);
+ if (freezing(current)) {
+ frozen_process(current);
+ task_unlock(current);
+ } else {
+ task_unlock(current);
+ return;
+ }
save = current->state;
pr_debug("%s entered refrigerator\n", current->comm);

- frozen_process(current);
spin_lock_irq(&current->sighand->siglock);
recalc_sigpending(); /* We sent fake signal, clean it up */
spin_unlock_irq(&current->sighand->siglock);
@@ -159,10 +167,12 @@ static unsigned int try_to_freeze_tasks(
if (is_user_space(p) == !freeze_user_space)
continue;

+ task_lock(p);
if (freezeable(p) && !frozen(p))
printk(KERN_ERR " %s\n", p->comm);

cancel_freezing(p);
+ task_unlock(p);
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
}

2007-02-26 11:32:28

by Oleg Nesterov

[permalink] [raw]
Subject: Re: [PATCH -mm 2/6] Freezer: Fix memory ordering in refrigerator

On 02/26, Rafael J. Wysocki wrote:
>
> From: Oleg Nesterov <[email protected]>
>
> refrigerator() can miss a wakeup, "wait event" loop needs a proper memory
> ordering.
>
> Signed-off-by: Oleg Nesterov <[email protected]>
> Signed-off-by: Rafael J. Wysocki <[email protected]>
> Acked-by: Pavel Machek <[email protected]>
> ---
> kernel/power/process.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> Index: linux-2.6.20-mm2/kernel/power/process.c
> ===================================================================
> --- linux-2.6.20-mm2.orig/kernel/power/process.c
> +++ linux-2.6.20-mm2/kernel/power/process.c
> @@ -47,8 +47,10 @@ void refrigerator(void)
> recalc_sigpending(); /* We sent fake signal, clean it up */
> spin_unlock_irq(&current->sighand->siglock);
>
> - while (frozen(current)) {
> - current->state = TASK_UNINTERRUPTIBLE;
> + for (;;) {
> + set_current_state(TASK_UNINTERRUPTIBLE);
> + if (!frozen(current))
> + break;
> schedule();
> }
> pr_debug("%s left refrigerator\n", current->comm);

This one is already in -mm tree.

Oleg.