]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
PM: hibernate: Do not subtract NR_FILE_MAPPED in minimum_image_size()
authorRainer Fiebig <jrf@mailbox.org>
Fri, 22 Dec 2017 10:13:59 +0000 (11:13 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 5 Jan 2018 13:46:25 +0000 (14:46 +0100)
s2disk/s2both may fail unnecessarily and erratically if NR_FILE_MAPPED
is high - for instance when using VMs with VirtualBox and perhaps VMware
Player. In those situations s2disk becomes unreliable and therefore
unusable.

A typical scenario is: user issues a s2disk and it fails. User issues
a second s2disk immediately after that and it succeeds.  And user
wonders why.

The problem is caused by minimum_image_size() in snapshot.c.  The
value it returns is roughly 100% too high because NR_FILE_MAPPED is
subtracted in its calculation.  Eventually the number of preallocated
image pages is falsely too low.

This doesn't matter as long as NR_FILE_MAPPED-values are in a normal
range or in 32bit-environments as the code allows for allocation of
additional pages from highmem.

But with the high values generated by VirtualBox-VMs (a 2-GB-VM causes
NR_FILE_MAPPED go up by 2 GB) it may lead to failure in 64bit-systems.

Not subtracting NR_FILE_MAPPED in minimum_image_size() solves the
problem.

I've done at least hundreds of successful s2both/s2disk now on an
x86_64 system (with and without VirtualBox) which gives me some
confidence that this is right.  It has turned s2disk/s2both from
unusable into 100% reliable.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=97201
Signed-off-by: Rainer Fiebig <jrf@mailbox.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
kernel/power/snapshot.c

index bce0464524d868ac47733035ba7d84e96927cbdb..3d37c279c09008b74c41a71abb850bfcdaa99e99 100644 (file)
@@ -1645,8 +1645,7 @@ static unsigned long free_unnecessary_pages(void)
  * [number of saveable pages] - [number of pages that can be freed in theory]
  *
  * where the second term is the sum of (1) reclaimable slab pages, (2) active
- * and (3) inactive anonymous pages, (4) active and (5) inactive file pages,
- * minus mapped file pages.
+ * and (3) inactive anonymous pages, (4) active and (5) inactive file pages.
  */
 static unsigned long minimum_image_size(unsigned long saveable)
 {
@@ -1656,8 +1655,7 @@ static unsigned long minimum_image_size(unsigned long saveable)
                + global_node_page_state(NR_ACTIVE_ANON)
                + global_node_page_state(NR_INACTIVE_ANON)
                + global_node_page_state(NR_ACTIVE_FILE)
-               + global_node_page_state(NR_INACTIVE_FILE)
-               - global_node_page_state(NR_FILE_MAPPED);
+               + global_node_page_state(NR_INACTIVE_FILE);
 
        return saveable <= size ? 0 : saveable - size;
 }