aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-30 08:19:38 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-30 20:49:33 -0400
commit8fd37a4c9822d58c93f764864582aa13112b1513 (patch)
tree6354cde58772d623391270c1a33e11ab66f66dad /kernel
parente0ae8fee0e11c1a8e9b45ab14ab5fe58d87f031d (diff)
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: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Toshi Kani <toshi.kani@hp.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/hibernate.c41
-rw-r--r--kernel/power/user.c22
2 files changed, 31 insertions, 32 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index b26f5f1e773e..d4e54053d009 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -644,22 +644,22 @@ int hibernate(void)
644 if (error) 644 if (error)
645 goto Exit; 645 goto Exit;
646 646
647 /* Allocate memory management structures */
648 error = create_basic_memory_bitmaps();
649 if (error)
650 goto Exit;
651
652 printk(KERN_INFO "PM: Syncing filesystems ... "); 647 printk(KERN_INFO "PM: Syncing filesystems ... ");
653 sys_sync(); 648 sys_sync();
654 printk("done.\n"); 649 printk("done.\n");
655 650
656 error = freeze_processes(); 651 error = freeze_processes();
657 if (error) 652 if (error)
658 goto Free_bitmaps; 653 goto Exit;
654
655 /* Allocate memory management structures */
656 error = create_basic_memory_bitmaps();
657 if (error)
658 goto Thaw;
659 659
660 error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); 660 error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
661 if (error || freezer_test_done) 661 if (error || freezer_test_done)
662 goto Thaw; 662 goto Free_bitmaps;
663 663
664 if (in_suspend) { 664 if (in_suspend) {
665 unsigned int flags = 0; 665 unsigned int flags = 0;
@@ -682,14 +682,13 @@ int hibernate(void)
682 pr_debug("PM: Image restored successfully.\n"); 682 pr_debug("PM: Image restored successfully.\n");
683 } 683 }
684 684
685 Free_bitmaps:
686 free_basic_memory_bitmaps();
685 Thaw: 687 Thaw:
686 thaw_processes(); 688 thaw_processes();
687 689
688 /* Don't bother checking whether freezer_test_done is true */ 690 /* Don't bother checking whether freezer_test_done is true */
689 freezer_test_done = false; 691 freezer_test_done = false;
690
691 Free_bitmaps:
692 free_basic_memory_bitmaps();
693 Exit: 692 Exit:
694 pm_notifier_call_chain(PM_POST_HIBERNATION); 693 pm_notifier_call_chain(PM_POST_HIBERNATION);
695 pm_restore_console(); 694 pm_restore_console();
@@ -806,21 +805,19 @@ static int software_resume(void)
806 pm_prepare_console(); 805 pm_prepare_console();
807 error = pm_notifier_call_chain(PM_RESTORE_PREPARE); 806 error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
808 if (error) 807 if (error)
809 goto close_finish; 808 goto Close_Finish;
810
811 error = create_basic_memory_bitmaps();
812 if (error)
813 goto close_finish;
814 809
815 pr_debug("PM: Preparing processes for restore.\n"); 810 pr_debug("PM: Preparing processes for restore.\n");
816 error = freeze_processes(); 811 error = freeze_processes();
817 if (error) { 812 if (error)
818 swsusp_close(FMODE_READ); 813 goto Close_Finish;
819 goto Done;
820 }
821 814
822 pr_debug("PM: Loading hibernation image.\n"); 815 pr_debug("PM: Loading hibernation image.\n");
823 816
817 error = create_basic_memory_bitmaps();
818 if (error)
819 goto Thaw;
820
824 error = swsusp_read(&flags); 821 error = swsusp_read(&flags);
825 swsusp_close(FMODE_READ); 822 swsusp_close(FMODE_READ);
826 if (!error) 823 if (!error)
@@ -828,9 +825,9 @@ static int software_resume(void)
828 825
829 printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n"); 826 printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
830 swsusp_free(); 827 swsusp_free();
831 thaw_processes();
832 Done:
833 free_basic_memory_bitmaps(); 828 free_basic_memory_bitmaps();
829 Thaw:
830 thaw_processes();
834 Finish: 831 Finish:
835 pm_notifier_call_chain(PM_POST_RESTORE); 832 pm_notifier_call_chain(PM_POST_RESTORE);
836 pm_restore_console(); 833 pm_restore_console();
@@ -840,7 +837,7 @@ static int software_resume(void)
840 mutex_unlock(&pm_mutex); 837 mutex_unlock(&pm_mutex);
841 pr_debug("PM: Hibernation image not present or could not be loaded.\n"); 838 pr_debug("PM: Hibernation image not present or could not be loaded.\n");
842 return error; 839 return error;
843close_finish: 840 Close_Finish:
844 swsusp_close(FMODE_READ); 841 swsusp_close(FMODE_READ);
845 goto Finish; 842 goto Finish;
846} 843}
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 4ed81e74f86f..63368163e98d 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -60,11 +60,6 @@ static int snapshot_open(struct inode *inode, struct file *filp)
60 error = -ENOSYS; 60 error = -ENOSYS;
61 goto Unlock; 61 goto Unlock;
62 } 62 }
63 if(create_basic_memory_bitmaps()) {
64 atomic_inc(&snapshot_device_available);
65 error = -ENOMEM;
66 goto Unlock;
67 }
68 nonseekable_open(inode, filp); 63 nonseekable_open(inode, filp);
69 data = &snapshot_state; 64 data = &snapshot_state;
70 filp->private_data = data; 65 filp->private_data = data;
@@ -90,10 +85,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
90 if (error) 85 if (error)
91 pm_notifier_call_chain(PM_POST_RESTORE); 86 pm_notifier_call_chain(PM_POST_RESTORE);
92 } 87 }
93 if (error) { 88 if (error)
94 free_basic_memory_bitmaps();
95 atomic_inc(&snapshot_device_available); 89 atomic_inc(&snapshot_device_available);
96 } 90
97 data->frozen = 0; 91 data->frozen = 0;
98 data->ready = 0; 92 data->ready = 0;
99 data->platform_support = 0; 93 data->platform_support = 0;
@@ -111,11 +105,11 @@ static int snapshot_release(struct inode *inode, struct file *filp)
111 lock_system_sleep(); 105 lock_system_sleep();
112 106
113 swsusp_free(); 107 swsusp_free();
114 free_basic_memory_bitmaps();
115 data = filp->private_data; 108 data = filp->private_data;
116 free_all_swap_pages(data->swap); 109 free_all_swap_pages(data->swap);
117 if (data->frozen) { 110 if (data->frozen) {
118 pm_restore_gfp_mask(); 111 pm_restore_gfp_mask();
112 free_basic_memory_bitmaps();
119 thaw_processes(); 113 thaw_processes();
120 } 114 }
121 pm_notifier_call_chain(data->mode == O_RDONLY ? 115 pm_notifier_call_chain(data->mode == O_RDONLY ?
@@ -220,14 +214,22 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
220 printk("done.\n"); 214 printk("done.\n");
221 215
222 error = freeze_processes(); 216 error = freeze_processes();
223 if (!error) 217 if (error)
218 break;
219
220 error = create_basic_memory_bitmaps();
221 if (error)
222 thaw_processes();
223 else
224 data->frozen = 1; 224 data->frozen = 1;
225
225 break; 226 break;
226 227
227 case SNAPSHOT_UNFREEZE: 228 case SNAPSHOT_UNFREEZE:
228 if (!data->frozen || data->ready) 229 if (!data->frozen || data->ready)
229 break; 230 break;
230 pm_restore_gfp_mask(); 231 pm_restore_gfp_mask();
232 free_basic_memory_bitmaps();
231 thaw_processes(); 233 thaw_processes();
232 data->frozen = 0; 234 data->frozen = 0;
233 break; 235 break;