[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#659363: Hibernate freezes on HP dc7900 with Linux 3.2 (regression)



Hi Udo,

Udo Richter wrote:

> It seems I am seeing the same bug too

Please test the attached patch[2], for example by following the following
instructions:

0. Prerequisites.

	apt-get install git build-essential

1. Get a copy of the kernel history if you don't already have it.

	git clone \
	  git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

2. Fetch point releases.

	cd linux
	git remote add -f stable \
	  git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

3. Configure, build, and test.

	cp /boot/config-$(uname -r) .config; # current configuration
	make localmodconfig; # optional: minimize configuration
	make deb-pkg; # optionally with -j<num> for parallel build
	dpkg -i ../<name of package>; # as root
	reboot
	... test test test ...

4. Hopefully it reproduces the bug.  Try the patch:

	git am -3sc <path to patch>
	make deb-pkg; # maybe with -j4
	dpkg -i ../<name of package>; # as root
	reboot
	... test test test ...

An alternative method for testing patches is described at [1].

Hope that helps,
Jonathan

[1] http://kernel-handbook.alioth.debian.org/ch-common-tasks.html#s-common-official
or the corresponding page from the debian-kernel-handbook package
[2] from http://thread.gmane.org/gmane.linux.kernel/1273425
From: Bojan Smojver <bojan@rexursive.com>
Date: Wed, 28 Mar 2012 10:41:12 +1100
Subject: Hibernation: lower/better control the amount of pages used for buffering

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 <bojan@rexursive.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 kernel/power/swap.c |   35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 11a594c4ba25..c0ff52e0bb19 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
  * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
- * Copyright (C) 2010 Bojan Smojver <bojan@rexursive.com>
+ * Copyright (C) 2010-2012 Bojan Smojver <bojan@rexursive.com>
  *
  * This file is released under the GPLv2.
  *
@@ -52,6 +52,15 @@
 
 #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.
+ */
+static inline unsigned long reqd_free_pages(void)
+{
+	return (nr_free_pages() / 4) * 3;
+}
+
 struct swap_map_page {
 	sector_t entries[MAP_PAGE_ENTRIES];
 	sector_t next_swap;
@@ -73,7 +82,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;
 };
 
@@ -317,8 +326,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:
@@ -353,11 +361,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;
@@ -405,7 +417,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
 
 
 /**
@@ -616,10 +628,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 +1141,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++) {
-- 
1.7.10.rc3


Reply to: