Commit a51f67a4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm-fix-for-3.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Power management fix for 3.3-rc2

Fix for a hibernate (s2disk) regression introduced during the 3.2
merge window that causes s2disk to trigger BUG_ON() in
freeze_workqueues_begin() if there is not enough swap space to save
the image.

* tag 'pm-fix-for-3.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  PM / Hibernate: Fix s2disk regression related to freezing workqueues
parents 0a962657 181e9bde
...@@ -39,6 +39,7 @@ extern bool __refrigerator(bool check_kthr_stop); ...@@ -39,6 +39,7 @@ extern bool __refrigerator(bool check_kthr_stop);
extern int freeze_processes(void); extern int freeze_processes(void);
extern int freeze_kernel_threads(void); extern int freeze_kernel_threads(void);
extern void thaw_processes(void); extern void thaw_processes(void);
extern void thaw_kernel_threads(void);
static inline bool try_to_freeze(void) static inline bool try_to_freeze(void)
{ {
...@@ -174,6 +175,7 @@ static inline bool __refrigerator(bool check_kthr_stop) { return false; } ...@@ -174,6 +175,7 @@ static inline bool __refrigerator(bool check_kthr_stop) { return false; }
static inline int freeze_processes(void) { return -ENOSYS; } static inline int freeze_processes(void) { return -ENOSYS; }
static inline int freeze_kernel_threads(void) { return -ENOSYS; } static inline int freeze_kernel_threads(void) { return -ENOSYS; }
static inline void thaw_processes(void) {} static inline void thaw_processes(void) {}
static inline void thaw_kernel_threads(void) {}
static inline bool try_to_freeze(void) { return false; } static inline bool try_to_freeze(void) { return false; }
......
...@@ -188,3 +188,22 @@ void thaw_processes(void) ...@@ -188,3 +188,22 @@ void thaw_processes(void)
printk("done.\n"); printk("done.\n");
} }
void thaw_kernel_threads(void)
{
struct task_struct *g, *p;
pm_nosig_freezing = false;
printk("Restarting kernel threads ... ");
thaw_workqueues();
read_lock(&tasklist_lock);
do_each_thread(g, p) {
if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
__thaw_task(p);
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
schedule();
printk("done.\n");
}
...@@ -274,6 +274,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, ...@@ -274,6 +274,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
swsusp_free(); swsusp_free();
memset(&data->handle, 0, sizeof(struct snapshot_handle)); memset(&data->handle, 0, sizeof(struct snapshot_handle));
data->ready = 0; data->ready = 0;
/*
* It is necessary to thaw kernel threads here, because
* SNAPSHOT_CREATE_IMAGE may be invoked directly after
* SNAPSHOT_FREE. In that case, if kernel threads were not
* thawed, the preallocation of memory carried out by
* hibernation_snapshot() might run into problems (i.e. it
* might fail or even deadlock).
*/
thaw_kernel_threads();
break; break;
case SNAPSHOT_PREF_IMAGE_SIZE: case SNAPSHOT_PREF_IMAGE_SIZE:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment