diff options
-rw-r--r-- | include/linux/freezer.h | 2 | ||||
-rw-r--r-- | kernel/power/process.c | 9 | ||||
-rw-r--r-- | kernel/power/user.c | 9 |
3 files changed, 20 insertions, 0 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h index a5386e3ee756..b5d6b6ad39f5 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -51,6 +51,7 @@ extern void refrigerator(void); extern int freeze_processes(void); extern int freeze_kernel_threads(void); extern void thaw_processes(void); +extern void thaw_kernel_threads(void); static inline int try_to_freeze(void) { @@ -185,6 +186,7 @@ static inline void refrigerator(void) {} static inline int freeze_processes(void) { return -ENOSYS; } static inline int freeze_kernel_threads(void) { return -ENOSYS; } static inline void thaw_processes(void) {} +static inline void thaw_kernel_threads(void) {} static inline int try_to_freeze(void) { return 0; } diff --git a/kernel/power/process.c b/kernel/power/process.c index addbbe5531bc..3d4b9544eeba 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -203,3 +203,12 @@ void thaw_processes(void) printk("done.\n"); } +void thaw_kernel_threads(void) +{ + printk("Restarting kernel threads ... "); + thaw_workqueues(); + thaw_tasks(true); + schedule(); + printk("done.\n"); +} + diff --git a/kernel/power/user.c b/kernel/power/user.c index 6d8f535c2b88..3565b1521c17 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -303,6 +303,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, swsusp_free(); memset(&data->handle, 0, sizeof(struct snapshot_handle)); 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; case SNAPSHOT_SET_IMAGE_SIZE: |