: Hibernation: lower/better control the amount of pages used for buffering
Subsystems (2)
PATCH v5 1/1 : Hibernation: lower/better control the amount of pages used for buffering
Hi Rafael,
Hopefully, this one has your comments addressed. Thanks for reviewing!
---------------------------------------
Hibernation/thaw improvements:
1. Set maximum number of pages for read buffering consistently, instead of inadvertently depending on the size of the sector type.
2. Use at most one quarter of free pages for read buffering.
3. Require that number of free pages when writing the image never falls below three quarters of total free pages available.
--- kernel/power/swap.c | 32 +++++++++++++++++++++----------- 1 files changed, 21 insertions(+), 11 deletions(-)
kernel/power/swap.c +21 -11
@@ -6,7 +6,7 @@* * Copyright (C) 1998,2001-2005 Pavel Machek <[email protected]> * Copyright (C) 2006 Rafael J. Wysocki <[email protected]> -* Copyright (C) 2010 Bojan Smojver <[email protected]> +* Copyright (C) 2010-2012 Bojan Smojver <[email protected]> * * This file is released under the GPLv2. *
@@ -51,6 +51,12 @@#define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) +/* +* Number of pages required to be kept free while writing the image. Always +* three quarters of all available pages before the writing starts. +*/ +#define reqd_free_pages () ((nr_free_pages() / 4) * 3) +struct swap_map_page {sector_t entries[MAP_PAGE_ENTRIES ];sector_t next_swap;
@@ -72,7 +78,7 @@ struct swap_map_handle {sector_t cur_swap;sector_t first_sector;unsigned int k; -unsigned long nr_free_pages, written; +unsigned long reqd_free_pages;u32 crc32; };
@@ -316,8 +322,7 @@ static int get_swap_writer(struct swap_map_handle *handle) goto err_rel; } handle->k =0 ; - handle->nr_free_pages =nr_free_pages () >>1 ; - handle->written =0 ; + handle->reqd_free_pages =reqd_free_pages (); handle->first_sector = handle->cur_swap;return 0 ; err_rel:
@@ -352,11 +357,15 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, handle->cur_swap = offset; handle->k =0 ; } -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);if (error) goto out; - handle->written =0 ; +/* +* Recalculate the number of required free pages, to make sure +* we never take more than a quarter. +*/ + handle->reqd_free_pages =reqd_free_pages (); } out:return error;
@@ -404,7 +413,7 @@ static int swap_writer_finish(struct swap_map_handle *handle,#define LZO_THREADS 3/* Maximum number of pages for read buffering. */ -#define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) +#define LZO_READ_PAGES 8192/**
@@ -615,10 +624,10 @@ static int save_image_lzo(struct swap_map_handle *handle, }/* -* Adjust number of free pages after all allocations have been done. -* We don't want to run out of pages when writing. +* Adjust the number of required free pages after all allocations have +* been done. We don't want to run out of pages when writing. */ - handle->nr_free_pages =nr_free_pages () >>1 ; + handle->reqd_free_pages =reqd_free_pages ();/* * Start the CRC32 thread.
@@ -1129,8 +1138,9 @@ static int load_image_lzo(struct swap_map_handle *handle,/* * Adjust number of pages for read buffering, in case we are short. +* Never take more than a quarter of all available pages. */ - read_pages = (nr_free_pages () -snapshot_get_image_size ()) >>1 ; + read_pages = (nr_free_pages () -snapshot_get_image_size ()) /4 ; read_pages =clamp_val (read_pages,LZO_CMP_PAGES ,LZO_READ_PAGES );for (i =0 ; i < read_pages; i++) {
---------------------------------------
Signature · 1 line
Bojan
Quoted 34 lines · Bojan Smojver
Hi Rafael,
Hopefully, this one has your comments addressed. Thanks for reviewing!
---------------------------------------
Hibernation/thaw improvements:1. Set maximum number of pages for read buffering consistently, instead of inadvertently depending on the size of the sector type.
2. Use at most one quarter of free pages for read buffering.
3. Require that number of free pages when writing the image never falls below three quarters of total free pages available.
Signed-off-by Bojan Smojver <[email protected]>--- kernel/power/swap.c | 32 +++++++++++++++++++++----------- 1 files changed, 21 insertions(+), 11 deletions(-)kernel/power/swap.c +1
-1@@ -6,7 +6,7 @@* * Copyright (C) 1998,2001-2005 Pavel Machek <[email protected]> * Copyright (C) 2006 Rafael J. Wysocki <[email protected]> -* Copyright (C) 2010 Bojan Smojver <[email protected]> +* Copyright (C) 2010-2012 Bojan Smojver <[email protected]> * * This file is released under the GPLv2. *
kernel/power/swap.c line 58
Quoted 8 lines
kernel/power/swap.c +5
-0@@ -51,6 +51,12 @@#define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) +/* +* Number of pages required to be kept free while writing the image. Always +* three quarters of all available pages before the writing starts. +*/ +#define reqd_free_pages () ((nr_free_pages() / 4) * 3)
If you define a macro, please use capital letters in the name. Also, the parentheses aren't necessary I think.
Perhaps it would be better to use a static inline function instead?
Rafael
Quoted 78 lines
kernel/power/swap.c +15
-11+struct swap_map_page {sector_t entries[MAP_PAGE_ENTRIES ];sector_t next_swap;@@ -72,7 +78,7 @@ struct swap_map_handle {sector_t cur_swap;sector_t first_sector;unsigned int k; -unsigned long nr_free_pages, written; +unsigned long reqd_free_pages;u32 crc32; };@@ -316,8 +322,7 @@ static int get_swap_writer(struct swap_map_handle *handle) goto err_rel; } handle->k =0 ; - handle->nr_free_pages =nr_free_pages () >>1 ; - handle->written =0 ; + handle->reqd_free_pages =reqd_free_pages (); handle->first_sector = handle->cur_swap;return 0 ; err_rel:@@ -352,11 +357,15 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, handle->cur_swap = offset; handle->k =0 ; } -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);if (error) goto out; - handle->written =0 ; +/* +* Recalculate the number of required free pages, to make sure +* we never take more than a quarter. +*/ + handle->reqd_free_pages =reqd_free_pages (); } out:return error;@@ -404,7 +413,7 @@ static int swap_writer_finish(struct swap_map_handle *handle,#define LZO_THREADS 3/* Maximum number of pages for read buffering. */ -#define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) +#define LZO_READ_PAGES 8192/** @@ -615,10 +624,10 @@ static int save_image_lzo(struct swap_map_handle *handle, }/* -* Adjust number of free pages after all allocations have been done. -* We don't want to run out of pages when writing. +* Adjust the number of required free pages after all allocations have +* been done. We don't want to run out of pages when writing. */ - handle->nr_free_pages =nr_free_pages () >>1 ; + handle->reqd_free_pages =reqd_free_pages ();/* * Start the CRC32 thread. @@ -1129,8 +1138,9 @@ static int load_image_lzo(struct swap_map_handle *handle,/* * Adjust number of pages for read buffering, in case we are short. +* Never take more than a quarter of all available pages. */ - read_pages = (nr_free_pages () -snapshot_get_image_size ()) >>1 ; + read_pages = (nr_free_pages () -snapshot_get_image_size ()) /4 ; read_pages =clamp_val (read_pages,LZO_CMP_PAGES ,LZO_READ_PAGES );for (i =0 ; i < read_pages; i++) { ---------------------------------------
Quoted 4 lines · Rafael J. Wysocki
If you define a macro, please use capital letters in the name. Also, the parentheses aren't necessary I think.
Perhaps it would be better to use a static inline function instead?
Hmm, was just following the nr_free_pages() definition in swap.h:
/* Definition of global_page_state not available yet */ #define nr_free_pages() global_page_state(NR_FREE_PAGES)
Still no good?
Signature · 1 line
Bojan
Quoted 4 lines · Bojan Smojver
Quoted 3 lines · Rafael J. Wysocki
If you define a macro, please use capital letters in the name. Also, the parentheses aren't necessary I think.
Quoted 8 lines
Quoted 1 line
Perhaps it would be better to use a static inline function instead?
Hmm, was just following the
nr_free_pages()definition inswap.h:/* Definition of
global_page_statenot available yet */ #definenr_free_pages()global_page_state(NR_FREE_PAGES)Still no good?
Not really, that should be a static inline too. :-)
Thanks,
Rafael
Quoted 1 line · Rafael J. Wysocki
Not really, that should be a static inline too. :-)
OK, I'll send you a v6 with REQD_FREE_PAGES.
Signature · 1 line
Bojan
Quoted 4 lines · Bojan Smojver
Quoted 1 line · Rafael J. Wysocki
Not really, that should be a static inline too. :-)
OK, I'll send you a v6 with
REQD_FREE_PAGES.
That's better, but what's wrong with a static inline, actually?
Those are preferred to macros nowadays.
Rafael
Quoted 1 line · Rafael J. Wysocki
That's better, but what's wrong with a static inline, actually?
Nothing, if that is what is required to get the patch accepted. :-)
I just thought that given that nr_free_pages() is already a macro with no side effects, it would make sense for reqd_free_pages() or REQD_FREE_PAGES to remain a macro.
But, if you insist on static inline, I'll do static inline. Let me know.
Signature · 1 line
Bojan
Quoted 10 lines · Bojan Smojver
Quoted 1 line · Rafael J. Wysocki
That's better, but what's wrong with a static inline, actually?
Nothing, if that is what is required to get the patch accepted. :-)
I just thought that given that
nr_free_pages()is already a macro with no side effects, it would make sense forreqd_free_pages()orREQD_FREE_PAGESto remain a macro.But, if you insist on static inline, I'll do static inline. Let me know.
Please do. You can even convert nr_free_pages() to a static inline while you're at it. :-)
Thanks,
Rafael
Quoted 1 line · Rafael J. Wysocki
Please do.
OK.
Quoted 2 lines
You can even convert
nr_free_pages()to a static inline while you're at it. :-)
Er, not straightforward, actually. I think the fact that there is a comment like below actually has something to do with it:
/* Definition of global_page_state not available yet */
So, I think I'm going to leave that be.
Signature · 1 line
Bojan