From 0709db6072c2e799eba1aa61bd19e0d7f38aa2cd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 6 May 2007 14:50:45 -0700 Subject: swsusp: use GFP_KERNEL for creating basic data structures Make swsusp call create_basic_memory_bitmaps() before processes are frozen, so that GFP_KERNEL allocations can be made in it. Additionally, ensure that the swsusp's userland interface won't be used while either pm_suspend_disk() or software_resume() is being executed. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/disk.c | 37 ++++++++++++++++++++++++++----------- kernel/power/power.h | 3 +++ kernel/power/snapshot.c | 8 ++++---- kernel/power/user.c | 10 +++++----- 4 files changed, 38 insertions(+), 20 deletions(-) (limited to 'kernel/power') diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 403bc3722fee..e518379b667a 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -130,28 +130,33 @@ int pm_suspend_disk(void) { int error; + /* The snapshot device should not be opened while we're running */ + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) + return -EBUSY; + + /* Allocate memory management structures */ + error = create_basic_memory_bitmaps(); + if (error) + goto Exit; + error = prepare_processes(); if (error) - return error; + goto Finish; if (pm_disk_mode == PM_DISK_TESTPROC) { printk("swsusp debug: Waiting for 5 seconds.\n"); mdelay(5000); goto Thaw; } - /* Allocate memory management structures */ - error = create_basic_memory_bitmaps(); - if (error) - goto Thaw; /* Free memory before shutting down devices. */ error = swsusp_shrink_memory(); if (error) - goto Finish; + goto Thaw; error = platform_prepare(); if (error) - goto Finish; + goto Thaw; suspend_console(); error = device_suspend(PMSG_FREEZE); @@ -186,7 +191,7 @@ int pm_suspend_disk(void) power_down(); else { swsusp_free(); - goto Finish; + goto Thaw; } } else { pr_debug("PM: Image restored successfully.\n"); @@ -199,10 +204,12 @@ int pm_suspend_disk(void) platform_finish(); device_resume(); resume_console(); - Finish: - free_basic_memory_bitmaps(); Thaw: unprepare_processes(); + Finish: + free_basic_memory_bitmaps(); + Exit: + atomic_inc(&snapshot_device_available); return error; } @@ -250,9 +257,15 @@ static int software_resume(void) if (error) goto Unlock; + /* The snapshot device should not be opened while we're running */ + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { + error = -EBUSY; + goto Unlock; + } + error = create_basic_memory_bitmaps(); if (error) - goto Unlock; + goto Finish; pr_debug("PM: Preparing processes for restore.\n"); error = prepare_processes(); @@ -290,6 +303,8 @@ static int software_resume(void) unprepare_processes(); Done: free_basic_memory_bitmaps(); + Finish: + atomic_inc(&snapshot_device_available); /* For success case, the suspend path will release the lock */ Unlock: mutex_unlock(&pm_mutex); diff --git a/kernel/power/power.h b/kernel/power/power.h index 1f8052bda0f7..a64d3f22de97 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -140,6 +140,9 @@ struct resume_swap_area { #define PMOPS_ENTER 2 #define PMOPS_FINISH 3 +/* If unset, the snapshot device cannot be open. */ +extern atomic_t snapshot_device_available; + /** * The bitmap is used for tracing allocated swap pages * diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index f66e4411795b..128da11f01c2 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -723,19 +723,19 @@ int create_basic_memory_bitmaps(void) BUG_ON(forbidden_pages_map || free_pages_map); - bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_ATOMIC); + bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL); if (!bm1) return -ENOMEM; - error = memory_bm_create(bm1, GFP_ATOMIC | __GFP_COLD, PG_ANY); + error = memory_bm_create(bm1, GFP_KERNEL, PG_ANY); if (error) goto Free_first_object; - bm2 = kzalloc(sizeof(struct memory_bitmap), GFP_ATOMIC); + bm2 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL); if (!bm2) goto Free_first_bitmap; - error = memory_bm_create(bm2, GFP_ATOMIC | __GFP_COLD, PG_ANY); + error = memory_bm_create(bm2, GFP_KERNEL, PG_ANY); if (error) goto Free_second_object; diff --git a/kernel/power/user.c b/kernel/power/user.c index bd1771f7a64e..72dbfd01408e 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -40,21 +40,21 @@ static struct snapshot_data { char platform_suspend; } snapshot_state; -static atomic_t device_available = ATOMIC_INIT(1); +atomic_t snapshot_device_available = ATOMIC_INIT(1); static int snapshot_open(struct inode *inode, struct file *filp) { struct snapshot_data *data; - if (!atomic_add_unless(&device_available, -1, 0)) + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) return -EBUSY; if ((filp->f_flags & O_ACCMODE) == O_RDWR) { - atomic_inc(&device_available); + atomic_inc(&snapshot_device_available); return -ENOSYS; } if(create_basic_memory_bitmaps()) { - atomic_inc(&device_available); + atomic_inc(&snapshot_device_available); return -ENOMEM; } nonseekable_open(inode, filp); @@ -92,7 +92,7 @@ static int snapshot_release(struct inode *inode, struct file *filp) enable_nonboot_cpus(); mutex_unlock(&pm_mutex); } - atomic_inc(&device_available); + atomic_inc(&snapshot_device_available); return 0; } -- cgit v1.2.3