PM / Hibernate: Do not leak memory in error/test code paths
authorRafael J. Wysocki <rjw@sisk.pl>
Tue, 22 Nov 2011 22:08:10 +0000 (23:08 +0100)
committerRafael J. Wysocki <rjw@sisk.pl>
Wed, 23 Nov 2011 20:03:38 +0000 (21:03 +0100)
The hibernation core code forgets to release memory preallocated
for hibernation if there's an error in its early stages or if test
modes causing hibernation_snapshot() to return early are used.  This
causes the system to be hardly usable, because the amount of
preallocated memory is usually huge.  Fix this problem.

Reported-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
kernel/power/hibernate.c

index 196c01268ebd73d50c0a5f4d52d913c9aff8bd8b..a6b0503574ee714b2cbe6c871741d298ad9ce5f7 100644 (file)
@@ -347,7 +347,7 @@ int hibernation_snapshot(int platform_mode)
 
        error = freeze_kernel_threads();
        if (error)
-               goto Close;
+               goto Cleanup;
 
        if (hibernation_test(TEST_FREEZER) ||
                hibernation_testmode(HIBERNATION_TESTPROC)) {
@@ -357,12 +357,14 @@ int hibernation_snapshot(int platform_mode)
                 * successful freezer test.
                 */
                freezer_test_done = true;
-               goto Close;
+               goto Cleanup;
        }
 
        error = dpm_prepare(PMSG_FREEZE);
-       if (error)
-               goto Complete_devices;
+       if (error) {
+               dpm_complete(msg);
+               goto Cleanup;
+       }
 
        suspend_console();
        pm_restrict_gfp_mask();
@@ -391,8 +393,6 @@ int hibernation_snapshot(int platform_mode)
                pm_restore_gfp_mask();
 
        resume_console();
-
- Complete_devices:
        dpm_complete(msg);
 
  Close:
@@ -402,6 +402,10 @@ int hibernation_snapshot(int platform_mode)
  Recover_platform:
        platform_recover(platform_mode);
        goto Resume_devices;
+
+ Cleanup:
+       swsusp_free();
+       goto Close;
 }
 
 /**