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 <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
1525a2ad76
commit
0709db6072
@ -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);
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user