Commit 8fd37a4c authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

PM / hibernate: Create memory bitmaps after freezing user space

The hibernation core uses special memory bitmaps during image
creation and restoration and traditionally those bitmaps are
allocated before freezing tasks, because in the past GFP_KERNEL
allocations might not work after all tasks had been frozen.

However, this is an anachronism, because hibernation_snapshot()
now calls hibernate_preallocate_memory() which allocates memory
for the image upfront anyway, so the memory bitmaps may be
allocated after freezing user space safely.

For this reason, move all of the create_basic_memory_bitmaps()
calls after freeze_processes() and all of the corresponding
free_basic_memory_bitmaps() calls before thaw_processes().

This will allow us to hold device_hotplug_lock around hibernation
without the need to worry about freezing issues with user space
processes attempting to acquire it via sysfs attributes after the
creation of memory bitmaps and before the freezing of tasks.
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarToshi Kani <toshi.kani@hp.com>
parent e0ae8fee
...@@ -644,22 +644,22 @@ int hibernate(void) ...@@ -644,22 +644,22 @@ int hibernate(void)
if (error) if (error)
goto Exit; goto Exit;
/* Allocate memory management structures */
error = create_basic_memory_bitmaps();
if (error)
goto Exit;
printk(KERN_INFO "PM: Syncing filesystems ... "); printk(KERN_INFO "PM: Syncing filesystems ... ");
sys_sync(); sys_sync();
printk("done.\n"); printk("done.\n");
error = freeze_processes(); error = freeze_processes();
if (error) if (error)
goto Free_bitmaps; goto Exit;
/* Allocate memory management structures */
error = create_basic_memory_bitmaps();
if (error)
goto Thaw;
error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
if (error || freezer_test_done) if (error || freezer_test_done)
goto Thaw; goto Free_bitmaps;
if (in_suspend) { if (in_suspend) {
unsigned int flags = 0; unsigned int flags = 0;
...@@ -682,14 +682,13 @@ int hibernate(void) ...@@ -682,14 +682,13 @@ int hibernate(void)
pr_debug("PM: Image restored successfully.\n"); pr_debug("PM: Image restored successfully.\n");
} }
Free_bitmaps:
free_basic_memory_bitmaps();
Thaw: Thaw:
thaw_processes(); thaw_processes();
/* Don't bother checking whether freezer_test_done is true */ /* Don't bother checking whether freezer_test_done is true */
freezer_test_done = false; freezer_test_done = false;
Free_bitmaps:
free_basic_memory_bitmaps();
Exit: Exit:
pm_notifier_call_chain(PM_POST_HIBERNATION); pm_notifier_call_chain(PM_POST_HIBERNATION);
pm_restore_console(); pm_restore_console();
...@@ -806,21 +805,19 @@ static int software_resume(void) ...@@ -806,21 +805,19 @@ static int software_resume(void)
pm_prepare_console(); pm_prepare_console();
error = pm_notifier_call_chain(PM_RESTORE_PREPARE); error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
if (error) if (error)
goto close_finish; goto Close_Finish;
error = create_basic_memory_bitmaps();
if (error)
goto close_finish;
pr_debug("PM: Preparing processes for restore.\n"); pr_debug("PM: Preparing processes for restore.\n");
error = freeze_processes(); error = freeze_processes();
if (error) { if (error)
swsusp_close(FMODE_READ); goto Close_Finish;
goto Done;
}
pr_debug("PM: Loading hibernation image.\n"); pr_debug("PM: Loading hibernation image.\n");
error = create_basic_memory_bitmaps();
if (error)
goto Thaw;
error = swsusp_read(&flags); error = swsusp_read(&flags);
swsusp_close(FMODE_READ); swsusp_close(FMODE_READ);
if (!error) if (!error)
...@@ -828,9 +825,9 @@ static int software_resume(void) ...@@ -828,9 +825,9 @@ static int software_resume(void)
printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n"); printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
swsusp_free(); swsusp_free();
thaw_processes();
Done:
free_basic_memory_bitmaps(); free_basic_memory_bitmaps();
Thaw:
thaw_processes();
Finish: Finish:
pm_notifier_call_chain(PM_POST_RESTORE); pm_notifier_call_chain(PM_POST_RESTORE);
pm_restore_console(); pm_restore_console();
...@@ -840,7 +837,7 @@ static int software_resume(void) ...@@ -840,7 +837,7 @@ static int software_resume(void)
mutex_unlock(&pm_mutex); mutex_unlock(&pm_mutex);
pr_debug("PM: Hibernation image not present or could not be loaded.\n"); pr_debug("PM: Hibernation image not present or could not be loaded.\n");
return error; return error;
close_finish: Close_Finish:
swsusp_close(FMODE_READ); swsusp_close(FMODE_READ);
goto Finish; goto Finish;
} }
......
...@@ -60,11 +60,6 @@ static int snapshot_open(struct inode *inode, struct file *filp) ...@@ -60,11 +60,6 @@ static int snapshot_open(struct inode *inode, struct file *filp)
error = -ENOSYS; error = -ENOSYS;
goto Unlock; goto Unlock;
} }
if(create_basic_memory_bitmaps()) {
atomic_inc(&snapshot_device_available);
error = -ENOMEM;
goto Unlock;
}
nonseekable_open(inode, filp); nonseekable_open(inode, filp);
data = &snapshot_state; data = &snapshot_state;
filp->private_data = data; filp->private_data = data;
...@@ -90,10 +85,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) ...@@ -90,10 +85,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
if (error) if (error)
pm_notifier_call_chain(PM_POST_RESTORE); pm_notifier_call_chain(PM_POST_RESTORE);
} }
if (error) { if (error)
free_basic_memory_bitmaps();
atomic_inc(&snapshot_device_available); atomic_inc(&snapshot_device_available);
}
data->frozen = 0; data->frozen = 0;
data->ready = 0; data->ready = 0;
data->platform_support = 0; data->platform_support = 0;
...@@ -111,11 +105,11 @@ static int snapshot_release(struct inode *inode, struct file *filp) ...@@ -111,11 +105,11 @@ static int snapshot_release(struct inode *inode, struct file *filp)
lock_system_sleep(); lock_system_sleep();
swsusp_free(); swsusp_free();
free_basic_memory_bitmaps();
data = filp->private_data; data = filp->private_data;
free_all_swap_pages(data->swap); free_all_swap_pages(data->swap);
if (data->frozen) { if (data->frozen) {
pm_restore_gfp_mask(); pm_restore_gfp_mask();
free_basic_memory_bitmaps();
thaw_processes(); thaw_processes();
} }
pm_notifier_call_chain(data->mode == O_RDONLY ? pm_notifier_call_chain(data->mode == O_RDONLY ?
...@@ -220,14 +214,22 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, ...@@ -220,14 +214,22 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
printk("done.\n"); printk("done.\n");
error = freeze_processes(); error = freeze_processes();
if (!error) if (error)
break;
error = create_basic_memory_bitmaps();
if (error)
thaw_processes();
else
data->frozen = 1; data->frozen = 1;
break; break;
case SNAPSHOT_UNFREEZE: case SNAPSHOT_UNFREEZE:
if (!data->frozen || data->ready) if (!data->frozen || data->ready)
break; break;
pm_restore_gfp_mask(); pm_restore_gfp_mask();
free_basic_memory_bitmaps();
thaw_processes(); thaw_processes();
data->frozen = 0; data->frozen = 0;
break; break;
......
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