Update hibernate watermark patch to latest tested version

This commit is contained in:
Josh Boyer 2012-04-10 20:10:54 -04:00
parent dfe7e131a2
commit bc0a9db03e

View File

@ -1,6 +1,39 @@
Hi Rafael,
One more version. Heeding Per's suggestion to optimise when
CONFIG_HIGHMEM is not configured.
---------------------------------------
Hibernation/thaw fixes/improvements:
1. Calculate the number of required free pages based on non-high memory
pages only, because that is where the buffers will come from.
2. Do not allocate memory for buffers from emergency pools, unless
absolutely required. Do not warn about and do not retry non-essential
failed allocations.
3. Do not check the amount of free pages left on every single page
write, but wait until one map is completely populated and then check.
4. Set maximum number of pages for read buffering consistently, instead
of inadvertently depending on the size of the sector type.
5. Fix copyright line, which I missed when I submitted the hibernation
threading patch.
6. Dispense with bit shifting arithmetic to improve readability.
Signed-off-by: Bojan Smojver <bojan@rexursive.com>
Signed-off-by: Per Olofsson <pelle@debian.org>
---
kernel/power/swap.c | 76 +++++++++++++++++++++++++++++++++++++++------------
1 files changed, 58 insertions(+), 18 deletions(-)
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 8742fd0..8a1c293 100644
--- a/kernel/power/swap.c --- a/kernel/power/swap.c
+++ a/kernel/power/swap.c +++ b/kernel/power/swap.c
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
* *
* Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz> * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
@ -10,23 +43,44 @@
* *
* This file is released under the GPLv2. * This file is released under the GPLv2.
* *
@@ -51,6 +51,15 @@ @@ -51,6 +51,36 @@
#define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1)
+/*
+ * Number of free pages that are not high.
+ */
+#ifdef CONFIG_HIGHMEM
+static unsigned long low_free_pages(void)
+{
+ struct zone *zone;
+ unsigned long free = 0;
+
+ for_each_populated_zone(zone)
+ if (!is_highmem(zone))
+ free += zone_page_state(zone, NR_FREE_PAGES);
+ return free;
+}
+#else
+static inline unsigned long low_free_pages(void)
+{
+ return nr_free_pages();
+}
+#endif
+
+/* +/*
+ * Number of pages required to be kept free while writing the image. Always + * Number of pages required to be kept free while writing the image. Always
+ * three quarters of all available pages before the writing starts. + * half of all available low pages before the writing starts.
+ */ + */
+static inline unsigned long reqd_free_pages(void) +static inline unsigned long reqd_free_pages(void)
+{ +{
+ return (nr_free_pages() / 4) * 3; + return low_free_pages() / 2;
+} +}
+ +
struct swap_map_page { struct swap_map_page {
sector_t entries[MAP_PAGE_ENTRIES]; sector_t entries[MAP_PAGE_ENTRIES];
sector_t next_swap; sector_t next_swap;
@@ -72,7 +81,7 @@ struct swap_map_handle { @@ -72,7 +102,7 @@ struct swap_map_handle {
sector_t cur_swap; sector_t cur_swap;
sector_t first_sector; sector_t first_sector;
unsigned int k; unsigned int k;
@ -35,7 +89,27 @@
u32 crc32; u32 crc32;
}; };
@@ -316,8 +325,7 @@ static int get_swap_writer(struct swap_map_handle *handle) @@ -265,14 +295,17 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
return -ENOSPC;
if (bio_chain) {
- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+ src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN |
+ __GFP_NORETRY);
if (src) {
copy_page(src, buf);
} else {
ret = hib_wait_on_bio_chain(bio_chain); /* Free pages */
if (ret)
return ret;
- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+ src = (void *)__get_free_page(__GFP_WAIT |
+ __GFP_NOWARN |
+ __GFP_NORETRY);
if (src) {
copy_page(src, buf);
} else {
@@ -316,8 +349,7 @@ static int get_swap_writer(struct swap_map_handle *handle)
goto err_rel; goto err_rel;
} }
handle->k = 0; handle->k = 0;
@ -45,25 +119,31 @@
handle->first_sector = handle->cur_swap; handle->first_sector = handle->cur_swap;
return 0; return 0;
err_rel: err_rel:
@@ -352,11 +360,15 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, @@ -351,12 +383,17 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
clear_page(handle->cur);
handle->cur_swap = offset; handle->cur_swap = offset;
handle->k = 0; handle->k = 0;
} - }
- if (bio_chain && ++handle->written > handle->nr_free_pages) { - if (bio_chain && ++handle->written > handle->nr_free_pages) {
+ if (bio_chain && nr_free_pages() <= handle->reqd_free_pages) { - error = hib_wait_on_bio_chain(bio_chain);
error = hib_wait_on_bio_chain(bio_chain); - if (error)
if (error) - goto out;
goto out;
- handle->written = 0; - handle->written = 0;
+
+ if (bio_chain && low_free_pages() <= handle->reqd_free_pages) {
+ error = hib_wait_on_bio_chain(bio_chain);
+ if (error)
+ goto out;
+ /* + /*
+ * Recalculate the number of required free pages, to make sure + * Recalculate the number of required free pages, to
+ * we never take more than a quarter. + * make sure we never take more than half.
+ */ + */
+ handle->reqd_free_pages = reqd_free_pages(); + handle->reqd_free_pages = reqd_free_pages();
+ }
} }
out: out:
return error; return error;
@@ -404,7 +416,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, @@ -404,7 +441,7 @@ static int swap_writer_finish(struct swap_map_handle *handle,
#define LZO_THREADS 3 #define LZO_THREADS 3
/* Maximum number of pages for read buffering. */ /* Maximum number of pages for read buffering. */
@ -72,7 +152,7 @@
/** /**
@@ -615,10 +627,10 @@ static int save_image_lzo(struct swap_map_handle *handle, @@ -615,10 +652,10 @@ static int save_image_lzo(struct swap_map_handle *handle,
} }
/* /*
@ -86,14 +166,33 @@
/* /*
* Start the CRC32 thread. * Start the CRC32 thread.
@@ -1129,8 +1141,9 @@ static int load_image_lzo(struct swap_map_handle *handle, @@ -1129,14 +1166,17 @@ static int load_image_lzo(struct swap_map_handle *handle,
/* /*
* Adjust number of pages for read buffering, in case we are short. * Adjust number of pages for read buffering, in case we are short.
+ * Never take more than a quarter of all available pages. + * Never take more than half of all available low pages.
*/ */
- read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1; - read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1;
+ read_pages = (nr_free_pages() - snapshot_get_image_size()) / 4; + read_pages = (low_free_pages() - snapshot_get_image_size()) / 2;
read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES); read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES);
for (i = 0; i < read_pages; i++) { for (i = 0; i < read_pages; i++) {
page[i] = (void *)__get_free_page(i < LZO_CMP_PAGES ?
__GFP_WAIT | __GFP_HIGH :
- __GFP_WAIT);
+ __GFP_WAIT | __GFP_NOWARN |
+ __GFP_NORETRY);
+
if (!page[i]) {
if (i < LZO_CMP_PAGES) {
ring_size = i;
---------------------------------------
--
Bojan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/