swsusp: Use GFP_KERNEL for creating basic data structures
Subsystems (2)
cover swsusp: Use GFP_KERNEL for creating basic data structures
Hi,
The first of the following two patches fixes a bug in the swsusp's userland interface and the second one makes swsusp use GFP_KERNEL allocations for creating its basic memory bitmaps.
Greetings,
Rafael
PATCH 1/2 swsusp: Fix error paths in snapshot_open
From: Rafael J. Wysocki <[email protected]>
We forget to increase device_available if there's an error in snapshot_open(), so the snapshot device cannot be open at all after snapshot_open() has returned an error.
--- kernel/power/user.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
kernel/power/user.c +6 -4
@@ -49,12 +49,14 @@ static int snapshot_open(struct inode *iif (!atomic_add_unless (&device_available,-1 ,0 ))return -EBUSY ; -if ((filp->f_flags &O_ACCMODE ) ==O_RDWR ) +if ((filp->f_flags &O_ACCMODE ) ==O_RDWR ) { +atomic_inc (&device_available);return -ENOSYS ; - -if (create_basic_memory_bitmaps ()) + } +if (create_basic_memory_bitmaps ()) { +atomic_inc (&device_available);return -ENOMEM ; - + }nonseekable_open (inode, filp); data = &snapshot_state; filp->private_data = data;
Re: [PATCH -mm 1/2] swsusp: Fix error paths in snapshot_open
Hi!
Quoted 5 lines
We forget to increase
device_availableif there's an error insnapshot_open(), so the snapshot device cannot be open at all aftersnapshot_open()has returned an error.Signed-off-by Rafael J. Wysocki <[email protected]>
ACK.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
PATCH 2/2 swsusp: Use GFP_KERNEL for creating basic data structures
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
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.
--- 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(-)
kernel/power/disk.c +26 -11
@@ -119,28 +119,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 );
@@ -175,7 +180,7 @@ int pm_suspend_disk(void)power_down (pm_disk_mode); else {swsusp_free (); - goto Finish; + goto Thaw; } }else {pr_debug ("PM: Image restored successfully.\n" );
@@ -188,10 +193,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; }
@@ -239,9 +246,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 ();
@@ -287,6 +300,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);
kernel/power/power.h +3 -0
@@ -141,6 +141,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 *
kernel/power/snapshot.c +4 -4
@@ -733,19 +733,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;
kernel/power/user.c +5 -5
@@ -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 inodeenable_nonboot_cpus ();mutex_unlock (&pm_mutex); } -atomic_inc (&device_available); +atomic_inc (&snapshot_device_available);return 0 ; }