All of lore.kernel.org
 help / color / mirror / Atom feed
* Swsusp patches applied to suspend-2.6#linux-next
@ 2010-09-27  5:43 Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 01/23] Hibernation: Split compression support out Nigel Cunningham
                   ` (53 more replies)
  0 siblings, 54 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi again Rafael.

As discussed, here are the patches, modified to apply against your current
linux-next tree. A new first patch splits compression support out into its
own file, removing the need to have two versions of the load_image and
save_image routines, minimising the changes to the remainder of the
patches and making things cleaner than would otherwise be the case.

On my laptop, single-threaded compression actually slows writing down from
175MB/s to around 100-120MB/s (depending on how well the image compresses).
Reading speed improves from 218MB/s to around 245MB/s. I expect that
multithreaded writing would bring the writing (and reading) speeds back
up. It's on my swsusp to do list :)

Nigel


^ permalink raw reply	[flat|nested] 113+ messages in thread

* [PATCH 01/23] Hibernation: Split compression support out.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 01/23] Hibernation: Split compression support out Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27 20:27   ` Rafael J. Wysocki
  2010-09-27 20:27   ` Rafael J. Wysocki
  2010-09-27  5:43 ` [PATCH 02/23] Record & display i/o speed post resume Nigel Cunningham
                   ` (51 subsequent siblings)
  53 siblings, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Separate compression support out into its own file, removing in
the process the duplication of the load_image and save_image
functions and some #includes from swap.c that are no longer
needed.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/Makefile   |    2 +-
 kernel/power/compress.c |  210 +++++++++++++++++++++++++++++
 kernel/power/compress.h |   23 +++
 kernel/power/swap.c     |  339 +++++------------------------------------------
 kernel/power/swap.h     |   28 ++++
 5 files changed, 296 insertions(+), 306 deletions(-)
 create mode 100644 kernel/power/compress.c
 create mode 100644 kernel/power/compress.h
 create mode 100644 kernel/power/swap.h

diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index f9063c6..2eb134d 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
 obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
-				   block_io.o
+				   block_io.o compress.o
 obj-$(CONFIG_SUSPEND_NVS)	+= nvs.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/compress.c b/kernel/power/compress.c
new file mode 100644
index 0000000..45725ea
--- /dev/null
+++ b/kernel/power/compress.c
@@ -0,0 +1,210 @@
+/*
+ * linux/kernel/power/compress.c
+ *
+ * This file provides functions for (optionally) compressing an
+ * image as it is being written and decompressing it at resume.
+ *
+ * Copyright (C) 2003-2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/lzo.h>
+#include <linux/vmalloc.h>
+
+#include "power.h"
+#include "swap.h"
+
+/* We need to remember how much compressed data we need to read. */
+#define LZO_HEADER	sizeof(size_t)
+
+/* Number of pages/bytes we'll compress at one time. */
+#define LZO_UNC_PAGES	32
+#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
+
+/* Number of pages/bytes we need for compressed data (worst case). */
+#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
+			             LZO_HEADER, PAGE_SIZE)
+#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
+
+static size_t off, unc_len, cmp_len;
+static unsigned char *unc, *cmp, *wrk, *page;
+
+void compress_image_cleanup(void)
+{
+	if (cmp) {
+		vfree(cmp);
+		cmp = NULL;
+	}
+
+	if (unc) {
+		vfree(unc);
+		unc = NULL;
+	}
+
+	if (wrk) {
+		vfree(wrk);
+		wrk = NULL;
+	}
+
+	if (page) {
+		free_page((unsigned long)page);
+		page = NULL;
+	}
+}
+
+int compress_image_init(void)
+{
+	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+	if (!page) {
+		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
+		return -ENOMEM;
+	}
+
+	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
+	unc = vmalloc(LZO_UNC_SIZE);
+	cmp = vmalloc(LZO_CMP_SIZE);
+
+	if (!wrk || !unc || !cmp) {
+		printk(KERN_ERR "PM: Failed to allocate memory for (de)compression.\n");
+		compress_image_cleanup();
+		return -ENOMEM;
+	}
+
+	off = 0;
+
+	return 0;
+}
+
+static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
+{
+	int ret;
+
+	if (!off)
+		return 0;
+
+	unc_len = off;
+	ret = lzo1x_1_compress(unc, unc_len, cmp + LZO_HEADER, &cmp_len, wrk);
+
+	if (ret < 0) {
+		printk(KERN_ERR "PM: LZO compression failed\n");
+		return -EIO;
+	}
+
+	if (unlikely(!cmp_len ||
+	             cmp_len > lzo1x_worst_compress(unc_len))) {
+		printk(KERN_ERR "PM: Invalid LZO compressed length\n");
+		return -EIO;
+	}
+
+	*(size_t *)cmp = cmp_len;
+
+	/*
+	 * Given we are writing one page at a time to disk, we copy
+	 * that much from the buffer, although the last bit will likely
+	 * be smaller than full page. This is OK - we saved the length
+	 * of the compressed data, so any garbage at the end will be
+	 * discarded when we read it.
+	 */
+	for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
+		memcpy(page, cmp + off, PAGE_SIZE);
+
+		ret = swap_write_page(handle, page, bio);
+		if (ret)
+			return ret;
+	}
+
+	off = 0;
+	return 0;
+}
+
+int compress_write(struct swap_map_handle *handle, char *buf, struct bio **bio,
+		int flags)
+{
+	int ret = 0;
+
+	if (flags & SF_NOCOMPRESS_MODE)
+		return swap_write_page(handle, buf, bio);
+
+	if (off == LZO_UNC_SIZE)
+		ret = compress_and_write(handle, bio);
+
+	memcpy(unc + off, buf, PAGE_SIZE);
+	off += PAGE_SIZE;
+	return ret;
+}
+
+void compress_write_finish(struct swap_map_handle *handle, struct bio **bio,
+		int flags)
+{
+	if (!(flags & SF_NOCOMPRESS_MODE))
+		compress_and_write(handle, bio);
+}
+
+static int read_and_decompress(struct swap_map_handle *handle)
+{
+	int error = swap_read_page(handle, page, NULL), off;
+	cmp_len = *(size_t *)page;
+
+	if (unlikely(!cmp_len ||
+	             cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
+		printk(KERN_ERR "PM: Invalid LZO compressed length\n");
+		return -1;
+	}
+
+	memcpy(cmp, page, PAGE_SIZE);
+	for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
+		error = swap_read_page(handle, page, NULL); /* sync */
+		if (error)
+			return error;
+
+		memcpy(cmp + off, page, PAGE_SIZE);
+	}
+
+	unc_len = LZO_UNC_SIZE;
+	error = lzo1x_decompress_safe(cmp + LZO_HEADER, cmp_len,
+	                              unc, &unc_len);
+	if (error < 0) {
+		printk(KERN_ERR "PM: LZO decompression failed\n");
+		return error;
+	}
+
+	if (unlikely(!unc_len ||
+	             unc_len > LZO_UNC_SIZE ||
+	             unc_len & (PAGE_SIZE - 1))) {
+		printk(KERN_ERR "PM: Invalid LZO uncompressed length\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int compress_read(struct swap_map_handle *handle, char *buf, struct bio **bio,
+		int flags)
+{
+	int ret = 0;
+
+	if (flags & SF_NOCOMPRESS_MODE)
+		return swap_read_page(handle, buf, bio);
+
+	if (!off) {
+		ret = read_and_decompress(handle);
+		if (ret)
+			return ret;
+	}
+
+	memcpy(buf, unc + off, PAGE_SIZE);
+	off += PAGE_SIZE;
+	if (off == unc_len)
+		off = 0;
+
+	return 0;
+}
+
+unsigned int compress_extra_pages(unsigned int base, unsigned int flags)
+{
+	return (flags & SF_NOCOMPRESS_MODE) ? 0 :
+		(base * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1 - base;
+}
diff --git a/kernel/power/compress.h b/kernel/power/compress.h
new file mode 100644
index 0000000..32abfc3
--- /dev/null
+++ b/kernel/power/compress.h
@@ -0,0 +1,23 @@
+/*
+ * linux/kernel/power/compress.h
+ *
+ * This file provides declarations for the functions used in compressing
+ * an image.
+ *
+ * Copyright (C) 2003-2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+struct swap_map_handle;
+
+int compress_image_init(void);
+void compress_image_cleanup(void);
+int compress_write(struct swap_map_handle *handle, char *page, struct bio **bio,
+		int flags);
+void compress_write_finish(struct swap_map_handle *handle, struct bio **bio,
+		int flags);
+int compress_read(struct swap_map_handle *handle, char *page, struct bio **bio,
+		int flags);
+unsigned int compress_extra_pages(unsigned int base, unsigned int flags);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 3dc0552..3c01105 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -11,23 +11,14 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/file.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-#include <linux/genhd.h>
-#include <linux/device.h>
 #include <linux/buffer_head.h>
-#include <linux/bio.h>
-#include <linux/blkdev.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
-#include <linux/pm.h>
 #include <linux/slab.h>
-#include <linux/lzo.h>
-#include <linux/vmalloc.h>
 
 #include "power.h"
+#include "compress.h"
+#include "swap.h"
 
 #define SWSUSP_SIG	"S1SUSPEND"
 
@@ -53,18 +44,6 @@ struct swap_map_page {
 	sector_t next_swap;
 };
 
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	sector_t cur_swap;
-	sector_t first_sector;
-	unsigned int k;
-};
-
 struct swsusp_header {
 	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
 	sector_t image;
@@ -301,7 +280,7 @@ err_close:
 	return ret;
 }
 
-static int swap_write_page(struct swap_map_handle *handle, void *buf,
+int swap_write_page(struct swap_map_handle *handle, void *buf,
 				struct bio **bio_chain)
 {
 	int error = 0;
@@ -359,25 +338,14 @@ static int swap_writer_finish(struct swap_map_handle *handle,
 	return error;
 }
 
-/* We need to remember how much compressed data we need to read. */
-#define LZO_HEADER	sizeof(size_t)
-
-/* Number of pages/bytes we'll compress at one time. */
-#define LZO_UNC_PAGES	32
-#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
-
-/* Number of pages/bytes we need for compressed data (worst case). */
-#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
-			             LZO_HEADER, PAGE_SIZE)
-#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
-
 /**
  *	save_image - save the suspend image data
  */
 
 static int save_image(struct swap_map_handle *handle,
                       struct snapshot_handle *snapshot,
-                      unsigned int nr_to_write)
+                      unsigned int nr_to_write,
+		      int flags)
 {
 	unsigned int m;
 	int ret;
@@ -399,13 +367,14 @@ static int save_image(struct swap_map_handle *handle,
 		ret = snapshot_read_next(snapshot);
 		if (ret <= 0)
 			break;
-		ret = swap_write_page(handle, data_of(*snapshot), &bio);
+		ret = compress_write(handle, data_of(*snapshot), &bio, flags);
 		if (ret)
 			break;
 		if (!(nr_pages % m))
 			printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
+	compress_write_finish(handle, &bio, flags);
 	err2 = hib_wait_on_bio_chain(&bio);
 	do_gettimeofday(&stop);
 	if (!ret)
@@ -420,136 +389,6 @@ static int save_image(struct swap_map_handle *handle,
 
 
 /**
- * save_image_lzo - Save the suspend image data compressed with LZO.
- * @handle: Swap mam handle to use for saving the image.
- * @snapshot: Image to read data from.
- * @nr_to_write: Number of pages to save.
- */
-static int save_image_lzo(struct swap_map_handle *handle,
-                          struct snapshot_handle *snapshot,
-                          unsigned int nr_to_write)
-{
-	unsigned int m;
-	int ret = 0;
-	int nr_pages;
-	int err2;
-	struct bio *bio;
-	struct timeval start;
-	struct timeval stop;
-	size_t off, unc_len, cmp_len;
-	unsigned char *unc, *cmp, *wrk, *page;
-
-	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-	if (!page) {
-		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
-		return -ENOMEM;
-	}
-
-	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
-	if (!wrk) {
-		printk(KERN_ERR "PM: Failed to allocate LZO workspace\n");
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	unc = vmalloc(LZO_UNC_SIZE);
-	if (!unc) {
-		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
-		vfree(wrk);
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	cmp = vmalloc(LZO_CMP_SIZE);
-	if (!cmp) {
-		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
-		vfree(unc);
-		vfree(wrk);
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	printk(KERN_INFO
-		"PM: Compressing and saving image data (%u pages) ...     ",
-		nr_to_write);
-	m = nr_to_write / 100;
-	if (!m)
-		m = 1;
-	nr_pages = 0;
-	bio = NULL;
-	do_gettimeofday(&start);
-	for (;;) {
-		for (off = 0; off < LZO_UNC_SIZE; off += PAGE_SIZE) {
-			ret = snapshot_read_next(snapshot);
-			if (ret < 0)
-				goto out_finish;
-
-			if (!ret)
-				break;
-
-			memcpy(unc + off, data_of(*snapshot), PAGE_SIZE);
-
-			if (!(nr_pages % m))
-				printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
-			nr_pages++;
-		}
-
-		if (!off)
-			break;
-
-		unc_len = off;
-		ret = lzo1x_1_compress(unc, unc_len,
-		                       cmp + LZO_HEADER, &cmp_len, wrk);
-		if (ret < 0) {
-			printk(KERN_ERR "PM: LZO compression failed\n");
-			break;
-		}
-
-		if (unlikely(!cmp_len ||
-		             cmp_len > lzo1x_worst_compress(unc_len))) {
-			printk(KERN_ERR "PM: Invalid LZO compressed length\n");
-			ret = -1;
-			break;
-		}
-
-		*(size_t *)cmp = cmp_len;
-
-		/*
-		 * Given we are writing one page at a time to disk, we copy
-		 * that much from the buffer, although the last bit will likely
-		 * be smaller than full page. This is OK - we saved the length
-		 * of the compressed data, so any garbage at the end will be
-		 * discarded when we read it.
-		 */
-		for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-			memcpy(page, cmp + off, PAGE_SIZE);
-
-			ret = swap_write_page(handle, page, &bio);
-			if (ret)
-				goto out_finish;
-		}
-	}
-
-out_finish:
-	err2 = hib_wait_on_bio_chain(&bio);
-	do_gettimeofday(&stop);
-	if (!ret)
-		ret = err2;
-	if (!ret)
-		printk(KERN_CONT "\b\b\b\bdone\n");
-	else
-		printk(KERN_CONT "\n");
-	swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
-
-	vfree(cmp);
-	vfree(unc);
-	vfree(wrk);
-	free_page((unsigned long)page);
-
-	return ret;
-}
-
-/**
  *	enough_swap - Make sure we have enough swap to save the image.
  *
  *	Returns TRUE or FALSE after checking the total amount of swap
@@ -563,8 +402,8 @@ static int enough_swap(unsigned int nr_pages, unsigned int flags)
 
 	pr_debug("PM: Free swap pages: %u\n", free_swap);
 
-	required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ?
-		nr_pages : (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1);
+	required = PAGES_FOR_IO + nr_pages +
+		compress_extra_pages(nr_pages, flags);
 	return free_swap > required;
 }
 
@@ -584,12 +423,18 @@ int swsusp_write(unsigned int flags)
 	struct snapshot_handle snapshot;
 	struct swsusp_info *header;
 	unsigned long pages;
-	int error;
+	int error = 0;
+
+	if (!(flags & SF_NOCOMPRESS_MODE))
+		error = compress_image_init();
+	if (error)
+		return error;
 
 	pages = snapshot_get_image_size();
 	error = get_swap_writer(&handle);
 	if (error) {
 		printk(KERN_ERR "PM: Cannot get swap writer\n");
+		compress_image_cleanup();
 		return error;
 	}
 	if (!enough_swap(pages, flags)) {
@@ -607,12 +452,10 @@ int swsusp_write(unsigned int flags)
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
 	error = swap_write_page(&handle, header, NULL);
-	if (!error) {
-		error = (flags & SF_NOCOMPRESS_MODE) ?
-			save_image(&handle, &snapshot, pages - 1) :
-			save_image_lzo(&handle, &snapshot, pages - 1);
-	}
+	if (!error)
+		error = save_image(&handle, &snapshot, pages - 1, flags);
 out_finish:
+	compress_image_cleanup();
 	error = swap_writer_finish(&handle, flags, error);
 	return error;
 }
@@ -652,7 +495,7 @@ static int get_swap_reader(struct swap_map_handle *handle,
 	return 0;
 }
 
-static int swap_read_page(struct swap_map_handle *handle, void *buf,
+int swap_read_page(struct swap_map_handle *handle, void *buf,
 				struct bio **bio_chain)
 {
 	sector_t offset;
@@ -693,7 +536,7 @@ static int swap_reader_finish(struct swap_map_handle *handle)
 
 static int load_image(struct swap_map_handle *handle,
                       struct snapshot_handle *snapshot,
-                      unsigned int nr_to_read)
+                      unsigned int nr_to_read, int flags)
 {
 	unsigned int m;
 	int error = 0;
@@ -715,7 +558,7 @@ static int load_image(struct swap_map_handle *handle,
 		error = snapshot_write_next(snapshot);
 		if (error <= 0)
 			break;
-		error = swap_read_page(handle, data_of(*snapshot), &bio);
+		error = compress_read(handle, data_of(*snapshot), &bio, flags);
 		if (error)
 			break;
 		if (snapshot->sync_read)
@@ -742,127 +585,6 @@ static int load_image(struct swap_map_handle *handle,
 }
 
 /**
- * load_image_lzo - Load compressed image data and decompress them with LZO.
- * @handle: Swap map handle to use for loading data.
- * @snapshot: Image to copy uncompressed data into.
- * @nr_to_read: Number of pages to load.
- */
-static int load_image_lzo(struct swap_map_handle *handle,
-                          struct snapshot_handle *snapshot,
-                          unsigned int nr_to_read)
-{
-	unsigned int m;
-	int error = 0;
-	struct timeval start;
-	struct timeval stop;
-	unsigned nr_pages;
-	size_t off, unc_len, cmp_len;
-	unsigned char *unc, *cmp, *page;
-
-	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-	if (!page) {
-		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
-		return -ENOMEM;
-	}
-
-	unc = vmalloc(LZO_UNC_SIZE);
-	if (!unc) {
-		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	cmp = vmalloc(LZO_CMP_SIZE);
-	if (!cmp) {
-		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
-		vfree(unc);
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	printk(KERN_INFO
-		"PM: Loading and decompressing image data (%u pages) ...     ",
-		nr_to_read);
-	m = nr_to_read / 100;
-	if (!m)
-		m = 1;
-	nr_pages = 0;
-	do_gettimeofday(&start);
-
-	error = snapshot_write_next(snapshot);
-	if (error <= 0)
-		goto out_finish;
-
-	for (;;) {
-		error = swap_read_page(handle, page, NULL); /* sync */
-		if (error)
-			break;
-
-		cmp_len = *(size_t *)page;
-		if (unlikely(!cmp_len ||
-		             cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
-			printk(KERN_ERR "PM: Invalid LZO compressed length\n");
-			error = -1;
-			break;
-		}
-
-		memcpy(cmp, page, PAGE_SIZE);
-		for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-			error = swap_read_page(handle, page, NULL); /* sync */
-			if (error)
-				goto out_finish;
-
-			memcpy(cmp + off, page, PAGE_SIZE);
-		}
-
-		unc_len = LZO_UNC_SIZE;
-		error = lzo1x_decompress_safe(cmp + LZO_HEADER, cmp_len,
-		                              unc, &unc_len);
-		if (error < 0) {
-			printk(KERN_ERR "PM: LZO decompression failed\n");
-			break;
-		}
-
-		if (unlikely(!unc_len ||
-		             unc_len > LZO_UNC_SIZE ||
-		             unc_len & (PAGE_SIZE - 1))) {
-			printk(KERN_ERR "PM: Invalid LZO uncompressed length\n");
-			error = -1;
-			break;
-		}
-
-		for (off = 0; off < unc_len; off += PAGE_SIZE) {
-			memcpy(data_of(*snapshot), unc + off, PAGE_SIZE);
-
-			if (!(nr_pages % m))
-				printk("\b\b\b\b%3d%%", nr_pages / m);
-			nr_pages++;
-
-			error = snapshot_write_next(snapshot);
-			if (error <= 0)
-				goto out_finish;
-		}
-	}
-
-out_finish:
-	do_gettimeofday(&stop);
-	if (!error) {
-		printk("\b\b\b\bdone\n");
-		snapshot_write_finalize(snapshot);
-		if (!snapshot_image_loaded(snapshot))
-			error = -ENODATA;
-	} else
-		printk("\n");
-	swsusp_show_speed(&start, &stop, nr_to_read, "Read");
-
-	vfree(cmp);
-	vfree(unc);
-	free_page((unsigned long)page);
-
-	return error;
-}
-
-/**
  *	swsusp_read - read the hibernation image.
  *	@flags_p: flags passed by the "frozen" kernel in the image header should
  *		  be written into this memeory location
@@ -870,15 +592,22 @@ out_finish:
 
 int swsusp_read(unsigned int *flags_p)
 {
-	int error;
+	int error = 0;
 	struct swap_map_handle handle;
 	struct snapshot_handle snapshot;
 	struct swsusp_info *header;
 
+	if (!(*flags_p & SF_NOCOMPRESS_MODE))
+		error = compress_image_init();
+	if (error)
+		return error;
+
 	memset(&snapshot, 0, sizeof(struct snapshot_handle));
 	error = snapshot_write_next(&snapshot);
-	if (error < PAGE_SIZE)
+	if (error < PAGE_SIZE) {
+		compress_image_cleanup();
 		return error < 0 ? error : -EFAULT;
+	}
 	header = (struct swsusp_info *)data_of(snapshot);
 	error = get_swap_reader(&handle, flags_p);
 	if (error)
@@ -886,12 +615,12 @@ int swsusp_read(unsigned int *flags_p)
 	if (!error)
 		error = swap_read_page(&handle, header, NULL);
 	if (!error) {
-		error = (*flags_p & SF_NOCOMPRESS_MODE) ?
-			load_image(&handle, &snapshot, header->pages - 1) :
-			load_image_lzo(&handle, &snapshot, header->pages - 1);
+		error = load_image(&handle, &snapshot, header->pages - 1,
+				*flags_p);
 	}
 	swap_reader_finish(&handle);
 end:
+	compress_image_cleanup();
 	if (!error)
 		pr_debug("PM: Image successfully loaded\n");
 	else
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
new file mode 100644
index 0000000..e9ad377
--- /dev/null
+++ b/kernel/power/swap.h
@@ -0,0 +1,28 @@
+/*
+ * linux/kernel/power/swap.h
+ *
+ * This file provides declarations for functions and structures from
+ * kernel/power/swap.c.
+ *
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+/**
+ *	The swap_map_handle structure is used for handling swap in
+ *	a file-alike way
+ */
+
+struct swap_map_handle {
+	struct swap_map_page *cur;
+	sector_t cur_swap;
+	sector_t first_sector;
+	unsigned int k;
+};
+
+int swap_write_page(struct swap_map_handle *handle, void *buf,
+				struct bio **bio_chain);
+int swap_read_page(struct swap_map_handle *handle, void *buf,
+				struct bio **bio_chain);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 01/23] Hibernation: Split compression support out.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (52 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Separate compression support out into its own file, removing in
the process the duplication of the load_image and save_image
functions and some #includes from swap.c that are no longer
needed.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/Makefile   |    2 +-
 kernel/power/compress.c |  210 +++++++++++++++++++++++++++++
 kernel/power/compress.h |   23 +++
 kernel/power/swap.c     |  339 +++++------------------------------------------
 kernel/power/swap.h     |   28 ++++
 5 files changed, 296 insertions(+), 306 deletions(-)
 create mode 100644 kernel/power/compress.c
 create mode 100644 kernel/power/compress.h
 create mode 100644 kernel/power/swap.h

diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index f9063c6..2eb134d 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
 obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
-				   block_io.o
+				   block_io.o compress.o
 obj-$(CONFIG_SUSPEND_NVS)	+= nvs.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/compress.c b/kernel/power/compress.c
new file mode 100644
index 0000000..45725ea
--- /dev/null
+++ b/kernel/power/compress.c
@@ -0,0 +1,210 @@
+/*
+ * linux/kernel/power/compress.c
+ *
+ * This file provides functions for (optionally) compressing an
+ * image as it is being written and decompressing it at resume.
+ *
+ * Copyright (C) 2003-2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/lzo.h>
+#include <linux/vmalloc.h>
+
+#include "power.h"
+#include "swap.h"
+
+/* We need to remember how much compressed data we need to read. */
+#define LZO_HEADER	sizeof(size_t)
+
+/* Number of pages/bytes we'll compress at one time. */
+#define LZO_UNC_PAGES	32
+#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
+
+/* Number of pages/bytes we need for compressed data (worst case). */
+#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
+			             LZO_HEADER, PAGE_SIZE)
+#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
+
+static size_t off, unc_len, cmp_len;
+static unsigned char *unc, *cmp, *wrk, *page;
+
+void compress_image_cleanup(void)
+{
+	if (cmp) {
+		vfree(cmp);
+		cmp = NULL;
+	}
+
+	if (unc) {
+		vfree(unc);
+		unc = NULL;
+	}
+
+	if (wrk) {
+		vfree(wrk);
+		wrk = NULL;
+	}
+
+	if (page) {
+		free_page((unsigned long)page);
+		page = NULL;
+	}
+}
+
+int compress_image_init(void)
+{
+	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+	if (!page) {
+		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
+		return -ENOMEM;
+	}
+
+	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
+	unc = vmalloc(LZO_UNC_SIZE);
+	cmp = vmalloc(LZO_CMP_SIZE);
+
+	if (!wrk || !unc || !cmp) {
+		printk(KERN_ERR "PM: Failed to allocate memory for (de)compression.\n");
+		compress_image_cleanup();
+		return -ENOMEM;
+	}
+
+	off = 0;
+
+	return 0;
+}
+
+static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
+{
+	int ret;
+
+	if (!off)
+		return 0;
+
+	unc_len = off;
+	ret = lzo1x_1_compress(unc, unc_len, cmp + LZO_HEADER, &cmp_len, wrk);
+
+	if (ret < 0) {
+		printk(KERN_ERR "PM: LZO compression failed\n");
+		return -EIO;
+	}
+
+	if (unlikely(!cmp_len ||
+	             cmp_len > lzo1x_worst_compress(unc_len))) {
+		printk(KERN_ERR "PM: Invalid LZO compressed length\n");
+		return -EIO;
+	}
+
+	*(size_t *)cmp = cmp_len;
+
+	/*
+	 * Given we are writing one page at a time to disk, we copy
+	 * that much from the buffer, although the last bit will likely
+	 * be smaller than full page. This is OK - we saved the length
+	 * of the compressed data, so any garbage at the end will be
+	 * discarded when we read it.
+	 */
+	for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
+		memcpy(page, cmp + off, PAGE_SIZE);
+
+		ret = swap_write_page(handle, page, bio);
+		if (ret)
+			return ret;
+	}
+
+	off = 0;
+	return 0;
+}
+
+int compress_write(struct swap_map_handle *handle, char *buf, struct bio **bio,
+		int flags)
+{
+	int ret = 0;
+
+	if (flags & SF_NOCOMPRESS_MODE)
+		return swap_write_page(handle, buf, bio);
+
+	if (off == LZO_UNC_SIZE)
+		ret = compress_and_write(handle, bio);
+
+	memcpy(unc + off, buf, PAGE_SIZE);
+	off += PAGE_SIZE;
+	return ret;
+}
+
+void compress_write_finish(struct swap_map_handle *handle, struct bio **bio,
+		int flags)
+{
+	if (!(flags & SF_NOCOMPRESS_MODE))
+		compress_and_write(handle, bio);
+}
+
+static int read_and_decompress(struct swap_map_handle *handle)
+{
+	int error = swap_read_page(handle, page, NULL), off;
+	cmp_len = *(size_t *)page;
+
+	if (unlikely(!cmp_len ||
+	             cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
+		printk(KERN_ERR "PM: Invalid LZO compressed length\n");
+		return -1;
+	}
+
+	memcpy(cmp, page, PAGE_SIZE);
+	for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
+		error = swap_read_page(handle, page, NULL); /* sync */
+		if (error)
+			return error;
+
+		memcpy(cmp + off, page, PAGE_SIZE);
+	}
+
+	unc_len = LZO_UNC_SIZE;
+	error = lzo1x_decompress_safe(cmp + LZO_HEADER, cmp_len,
+	                              unc, &unc_len);
+	if (error < 0) {
+		printk(KERN_ERR "PM: LZO decompression failed\n");
+		return error;
+	}
+
+	if (unlikely(!unc_len ||
+	             unc_len > LZO_UNC_SIZE ||
+	             unc_len & (PAGE_SIZE - 1))) {
+		printk(KERN_ERR "PM: Invalid LZO uncompressed length\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int compress_read(struct swap_map_handle *handle, char *buf, struct bio **bio,
+		int flags)
+{
+	int ret = 0;
+
+	if (flags & SF_NOCOMPRESS_MODE)
+		return swap_read_page(handle, buf, bio);
+
+	if (!off) {
+		ret = read_and_decompress(handle);
+		if (ret)
+			return ret;
+	}
+
+	memcpy(buf, unc + off, PAGE_SIZE);
+	off += PAGE_SIZE;
+	if (off == unc_len)
+		off = 0;
+
+	return 0;
+}
+
+unsigned int compress_extra_pages(unsigned int base, unsigned int flags)
+{
+	return (flags & SF_NOCOMPRESS_MODE) ? 0 :
+		(base * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1 - base;
+}
diff --git a/kernel/power/compress.h b/kernel/power/compress.h
new file mode 100644
index 0000000..32abfc3
--- /dev/null
+++ b/kernel/power/compress.h
@@ -0,0 +1,23 @@
+/*
+ * linux/kernel/power/compress.h
+ *
+ * This file provides declarations for the functions used in compressing
+ * an image.
+ *
+ * Copyright (C) 2003-2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+struct swap_map_handle;
+
+int compress_image_init(void);
+void compress_image_cleanup(void);
+int compress_write(struct swap_map_handle *handle, char *page, struct bio **bio,
+		int flags);
+void compress_write_finish(struct swap_map_handle *handle, struct bio **bio,
+		int flags);
+int compress_read(struct swap_map_handle *handle, char *page, struct bio **bio,
+		int flags);
+unsigned int compress_extra_pages(unsigned int base, unsigned int flags);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 3dc0552..3c01105 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -11,23 +11,14 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/file.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-#include <linux/genhd.h>
-#include <linux/device.h>
 #include <linux/buffer_head.h>
-#include <linux/bio.h>
-#include <linux/blkdev.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
-#include <linux/pm.h>
 #include <linux/slab.h>
-#include <linux/lzo.h>
-#include <linux/vmalloc.h>
 
 #include "power.h"
+#include "compress.h"
+#include "swap.h"
 
 #define SWSUSP_SIG	"S1SUSPEND"
 
@@ -53,18 +44,6 @@ struct swap_map_page {
 	sector_t next_swap;
 };
 
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	sector_t cur_swap;
-	sector_t first_sector;
-	unsigned int k;
-};
-
 struct swsusp_header {
 	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
 	sector_t image;
@@ -301,7 +280,7 @@ err_close:
 	return ret;
 }
 
-static int swap_write_page(struct swap_map_handle *handle, void *buf,
+int swap_write_page(struct swap_map_handle *handle, void *buf,
 				struct bio **bio_chain)
 {
 	int error = 0;
@@ -359,25 +338,14 @@ static int swap_writer_finish(struct swap_map_handle *handle,
 	return error;
 }
 
-/* We need to remember how much compressed data we need to read. */
-#define LZO_HEADER	sizeof(size_t)
-
-/* Number of pages/bytes we'll compress at one time. */
-#define LZO_UNC_PAGES	32
-#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
-
-/* Number of pages/bytes we need for compressed data (worst case). */
-#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
-			             LZO_HEADER, PAGE_SIZE)
-#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
-
 /**
  *	save_image - save the suspend image data
  */
 
 static int save_image(struct swap_map_handle *handle,
                       struct snapshot_handle *snapshot,
-                      unsigned int nr_to_write)
+                      unsigned int nr_to_write,
+		      int flags)
 {
 	unsigned int m;
 	int ret;
@@ -399,13 +367,14 @@ static int save_image(struct swap_map_handle *handle,
 		ret = snapshot_read_next(snapshot);
 		if (ret <= 0)
 			break;
-		ret = swap_write_page(handle, data_of(*snapshot), &bio);
+		ret = compress_write(handle, data_of(*snapshot), &bio, flags);
 		if (ret)
 			break;
 		if (!(nr_pages % m))
 			printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
+	compress_write_finish(handle, &bio, flags);
 	err2 = hib_wait_on_bio_chain(&bio);
 	do_gettimeofday(&stop);
 	if (!ret)
@@ -420,136 +389,6 @@ static int save_image(struct swap_map_handle *handle,
 
 
 /**
- * save_image_lzo - Save the suspend image data compressed with LZO.
- * @handle: Swap mam handle to use for saving the image.
- * @snapshot: Image to read data from.
- * @nr_to_write: Number of pages to save.
- */
-static int save_image_lzo(struct swap_map_handle *handle,
-                          struct snapshot_handle *snapshot,
-                          unsigned int nr_to_write)
-{
-	unsigned int m;
-	int ret = 0;
-	int nr_pages;
-	int err2;
-	struct bio *bio;
-	struct timeval start;
-	struct timeval stop;
-	size_t off, unc_len, cmp_len;
-	unsigned char *unc, *cmp, *wrk, *page;
-
-	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-	if (!page) {
-		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
-		return -ENOMEM;
-	}
-
-	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
-	if (!wrk) {
-		printk(KERN_ERR "PM: Failed to allocate LZO workspace\n");
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	unc = vmalloc(LZO_UNC_SIZE);
-	if (!unc) {
-		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
-		vfree(wrk);
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	cmp = vmalloc(LZO_CMP_SIZE);
-	if (!cmp) {
-		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
-		vfree(unc);
-		vfree(wrk);
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	printk(KERN_INFO
-		"PM: Compressing and saving image data (%u pages) ...     ",
-		nr_to_write);
-	m = nr_to_write / 100;
-	if (!m)
-		m = 1;
-	nr_pages = 0;
-	bio = NULL;
-	do_gettimeofday(&start);
-	for (;;) {
-		for (off = 0; off < LZO_UNC_SIZE; off += PAGE_SIZE) {
-			ret = snapshot_read_next(snapshot);
-			if (ret < 0)
-				goto out_finish;
-
-			if (!ret)
-				break;
-
-			memcpy(unc + off, data_of(*snapshot), PAGE_SIZE);
-
-			if (!(nr_pages % m))
-				printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
-			nr_pages++;
-		}
-
-		if (!off)
-			break;
-
-		unc_len = off;
-		ret = lzo1x_1_compress(unc, unc_len,
-		                       cmp + LZO_HEADER, &cmp_len, wrk);
-		if (ret < 0) {
-			printk(KERN_ERR "PM: LZO compression failed\n");
-			break;
-		}
-
-		if (unlikely(!cmp_len ||
-		             cmp_len > lzo1x_worst_compress(unc_len))) {
-			printk(KERN_ERR "PM: Invalid LZO compressed length\n");
-			ret = -1;
-			break;
-		}
-
-		*(size_t *)cmp = cmp_len;
-
-		/*
-		 * Given we are writing one page at a time to disk, we copy
-		 * that much from the buffer, although the last bit will likely
-		 * be smaller than full page. This is OK - we saved the length
-		 * of the compressed data, so any garbage at the end will be
-		 * discarded when we read it.
-		 */
-		for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-			memcpy(page, cmp + off, PAGE_SIZE);
-
-			ret = swap_write_page(handle, page, &bio);
-			if (ret)
-				goto out_finish;
-		}
-	}
-
-out_finish:
-	err2 = hib_wait_on_bio_chain(&bio);
-	do_gettimeofday(&stop);
-	if (!ret)
-		ret = err2;
-	if (!ret)
-		printk(KERN_CONT "\b\b\b\bdone\n");
-	else
-		printk(KERN_CONT "\n");
-	swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
-
-	vfree(cmp);
-	vfree(unc);
-	vfree(wrk);
-	free_page((unsigned long)page);
-
-	return ret;
-}
-
-/**
  *	enough_swap - Make sure we have enough swap to save the image.
  *
  *	Returns TRUE or FALSE after checking the total amount of swap
@@ -563,8 +402,8 @@ static int enough_swap(unsigned int nr_pages, unsigned int flags)
 
 	pr_debug("PM: Free swap pages: %u\n", free_swap);
 
-	required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ?
-		nr_pages : (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1);
+	required = PAGES_FOR_IO + nr_pages +
+		compress_extra_pages(nr_pages, flags);
 	return free_swap > required;
 }
 
@@ -584,12 +423,18 @@ int swsusp_write(unsigned int flags)
 	struct snapshot_handle snapshot;
 	struct swsusp_info *header;
 	unsigned long pages;
-	int error;
+	int error = 0;
+
+	if (!(flags & SF_NOCOMPRESS_MODE))
+		error = compress_image_init();
+	if (error)
+		return error;
 
 	pages = snapshot_get_image_size();
 	error = get_swap_writer(&handle);
 	if (error) {
 		printk(KERN_ERR "PM: Cannot get swap writer\n");
+		compress_image_cleanup();
 		return error;
 	}
 	if (!enough_swap(pages, flags)) {
@@ -607,12 +452,10 @@ int swsusp_write(unsigned int flags)
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
 	error = swap_write_page(&handle, header, NULL);
-	if (!error) {
-		error = (flags & SF_NOCOMPRESS_MODE) ?
-			save_image(&handle, &snapshot, pages - 1) :
-			save_image_lzo(&handle, &snapshot, pages - 1);
-	}
+	if (!error)
+		error = save_image(&handle, &snapshot, pages - 1, flags);
 out_finish:
+	compress_image_cleanup();
 	error = swap_writer_finish(&handle, flags, error);
 	return error;
 }
@@ -652,7 +495,7 @@ static int get_swap_reader(struct swap_map_handle *handle,
 	return 0;
 }
 
-static int swap_read_page(struct swap_map_handle *handle, void *buf,
+int swap_read_page(struct swap_map_handle *handle, void *buf,
 				struct bio **bio_chain)
 {
 	sector_t offset;
@@ -693,7 +536,7 @@ static int swap_reader_finish(struct swap_map_handle *handle)
 
 static int load_image(struct swap_map_handle *handle,
                       struct snapshot_handle *snapshot,
-                      unsigned int nr_to_read)
+                      unsigned int nr_to_read, int flags)
 {
 	unsigned int m;
 	int error = 0;
@@ -715,7 +558,7 @@ static int load_image(struct swap_map_handle *handle,
 		error = snapshot_write_next(snapshot);
 		if (error <= 0)
 			break;
-		error = swap_read_page(handle, data_of(*snapshot), &bio);
+		error = compress_read(handle, data_of(*snapshot), &bio, flags);
 		if (error)
 			break;
 		if (snapshot->sync_read)
@@ -742,127 +585,6 @@ static int load_image(struct swap_map_handle *handle,
 }
 
 /**
- * load_image_lzo - Load compressed image data and decompress them with LZO.
- * @handle: Swap map handle to use for loading data.
- * @snapshot: Image to copy uncompressed data into.
- * @nr_to_read: Number of pages to load.
- */
-static int load_image_lzo(struct swap_map_handle *handle,
-                          struct snapshot_handle *snapshot,
-                          unsigned int nr_to_read)
-{
-	unsigned int m;
-	int error = 0;
-	struct timeval start;
-	struct timeval stop;
-	unsigned nr_pages;
-	size_t off, unc_len, cmp_len;
-	unsigned char *unc, *cmp, *page;
-
-	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-	if (!page) {
-		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
-		return -ENOMEM;
-	}
-
-	unc = vmalloc(LZO_UNC_SIZE);
-	if (!unc) {
-		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	cmp = vmalloc(LZO_CMP_SIZE);
-	if (!cmp) {
-		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
-		vfree(unc);
-		free_page((unsigned long)page);
-		return -ENOMEM;
-	}
-
-	printk(KERN_INFO
-		"PM: Loading and decompressing image data (%u pages) ...     ",
-		nr_to_read);
-	m = nr_to_read / 100;
-	if (!m)
-		m = 1;
-	nr_pages = 0;
-	do_gettimeofday(&start);
-
-	error = snapshot_write_next(snapshot);
-	if (error <= 0)
-		goto out_finish;
-
-	for (;;) {
-		error = swap_read_page(handle, page, NULL); /* sync */
-		if (error)
-			break;
-
-		cmp_len = *(size_t *)page;
-		if (unlikely(!cmp_len ||
-		             cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
-			printk(KERN_ERR "PM: Invalid LZO compressed length\n");
-			error = -1;
-			break;
-		}
-
-		memcpy(cmp, page, PAGE_SIZE);
-		for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-			error = swap_read_page(handle, page, NULL); /* sync */
-			if (error)
-				goto out_finish;
-
-			memcpy(cmp + off, page, PAGE_SIZE);
-		}
-
-		unc_len = LZO_UNC_SIZE;
-		error = lzo1x_decompress_safe(cmp + LZO_HEADER, cmp_len,
-		                              unc, &unc_len);
-		if (error < 0) {
-			printk(KERN_ERR "PM: LZO decompression failed\n");
-			break;
-		}
-
-		if (unlikely(!unc_len ||
-		             unc_len > LZO_UNC_SIZE ||
-		             unc_len & (PAGE_SIZE - 1))) {
-			printk(KERN_ERR "PM: Invalid LZO uncompressed length\n");
-			error = -1;
-			break;
-		}
-
-		for (off = 0; off < unc_len; off += PAGE_SIZE) {
-			memcpy(data_of(*snapshot), unc + off, PAGE_SIZE);
-
-			if (!(nr_pages % m))
-				printk("\b\b\b\b%3d%%", nr_pages / m);
-			nr_pages++;
-
-			error = snapshot_write_next(snapshot);
-			if (error <= 0)
-				goto out_finish;
-		}
-	}
-
-out_finish:
-	do_gettimeofday(&stop);
-	if (!error) {
-		printk("\b\b\b\bdone\n");
-		snapshot_write_finalize(snapshot);
-		if (!snapshot_image_loaded(snapshot))
-			error = -ENODATA;
-	} else
-		printk("\n");
-	swsusp_show_speed(&start, &stop, nr_to_read, "Read");
-
-	vfree(cmp);
-	vfree(unc);
-	free_page((unsigned long)page);
-
-	return error;
-}
-
-/**
  *	swsusp_read - read the hibernation image.
  *	@flags_p: flags passed by the "frozen" kernel in the image header should
  *		  be written into this memeory location
@@ -870,15 +592,22 @@ out_finish:
 
 int swsusp_read(unsigned int *flags_p)
 {
-	int error;
+	int error = 0;
 	struct swap_map_handle handle;
 	struct snapshot_handle snapshot;
 	struct swsusp_info *header;
 
+	if (!(*flags_p & SF_NOCOMPRESS_MODE))
+		error = compress_image_init();
+	if (error)
+		return error;
+
 	memset(&snapshot, 0, sizeof(struct snapshot_handle));
 	error = snapshot_write_next(&snapshot);
-	if (error < PAGE_SIZE)
+	if (error < PAGE_SIZE) {
+		compress_image_cleanup();
 		return error < 0 ? error : -EFAULT;
+	}
 	header = (struct swsusp_info *)data_of(snapshot);
 	error = get_swap_reader(&handle, flags_p);
 	if (error)
@@ -886,12 +615,12 @@ int swsusp_read(unsigned int *flags_p)
 	if (!error)
 		error = swap_read_page(&handle, header, NULL);
 	if (!error) {
-		error = (*flags_p & SF_NOCOMPRESS_MODE) ?
-			load_image(&handle, &snapshot, header->pages - 1) :
-			load_image_lzo(&handle, &snapshot, header->pages - 1);
+		error = load_image(&handle, &snapshot, header->pages - 1,
+				*flags_p);
 	}
 	swap_reader_finish(&handle);
 end:
+	compress_image_cleanup();
 	if (!error)
 		pr_debug("PM: Image successfully loaded\n");
 	else
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
new file mode 100644
index 0000000..e9ad377
--- /dev/null
+++ b/kernel/power/swap.h
@@ -0,0 +1,28 @@
+/*
+ * linux/kernel/power/swap.h
+ *
+ * This file provides declarations for functions and structures from
+ * kernel/power/swap.c.
+ *
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+/**
+ *	The swap_map_handle structure is used for handling swap in
+ *	a file-alike way
+ */
+
+struct swap_map_handle {
+	struct swap_map_page *cur;
+	sector_t cur_swap;
+	sector_t first_sector;
+	unsigned int k;
+};
+
+int swap_write_page(struct swap_map_handle *handle, void *buf,
+				struct bio **bio_chain);
+int swap_read_page(struct swap_map_handle *handle, void *buf,
+				struct bio **bio_chain);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 01/23] Hibernation: Split compression support out Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27 20:06   ` Rafael J. Wysocki
  2010-09-27 20:06   ` Rafael J. Wysocki
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (50 subsequent siblings)
  53 siblings, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Record the speed at which the image is written and read, and
display it to the user post-resume.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/hibernate.c |   11 ++++++++++-
 kernel/power/power.h     |    3 ++-
 kernel/power/swap.c      |   14 +++++++++++---
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 6c9c9dc..0cd1f05 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
  *	@msg -		introductory message to print
  */
 
-void swsusp_show_speed(struct timeval *start, struct timeval *stop,
+int swsusp_show_speed(struct timeval *start, struct timeval *stop,
 			unsigned nr_pages, char *msg)
 {
 	s64 elapsed_centisecs64;
@@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
 			msg, k,
 			centisecs / 100, centisecs % 100,
 			kps / 1000, (kps % 1000) / 10);
+	return kps / 1000;
 }
 
 /**
@@ -648,6 +649,14 @@ int hibernate(void)
 			power_down();
 	} else {
 		pr_debug("PM: Image restored successfully.\n");
+		if (write_speed)
+			pr_debug("PM: Image written at %u MB/s.\n",
+					(u8) write_speed);
+		write_speed = 0;
+		if (read_speed)
+			pr_debug("PM: Image read at %u MB/s.\n",
+					(u8) read_speed);
+		read_speed = 0;
 	}
 
  Thaw:
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 03634be..22f8607 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
 extern int hibernation_restore(int platform_mode);
 extern int hibernation_platform_enter(void);
 
+extern char __nosavedata write_speed, read_speed;
 #else /* !CONFIG_HIBERNATION */
 
 static inline void hibernate_image_size_init(void) {}
@@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
 
 struct timeval;
 /* kernel/power/swsusp.c */
-extern void swsusp_show_speed(struct timeval *, struct timeval *,
+extern int swsusp_show_speed(struct timeval *, struct timeval *,
 				unsigned int, char *);
 
 #ifdef CONFIG_SUSPEND
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 3c01105..caf4db8 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -45,7 +45,8 @@ struct swap_map_page {
 };
 
 struct swsusp_header {
-	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
+	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
+	char write_speed;
 	sector_t image;
 	unsigned int flags;	/* Flags to pass to the "boot" kernel */
 	char	orig_sig[10];
@@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
 
 static unsigned short root_swap = 0xffff;
 struct block_device *hib_resume_bdev;
+char __nosavedata write_speed, read_speed;
 
 /*
  * Saving part
@@ -175,6 +177,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
 	    !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
 		memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
+		swsusp_header->write_speed = write_speed;
 		swsusp_header->image = handle->first_sector;
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
@@ -354,6 +357,7 @@ static int save_image(struct swap_map_handle *handle,
 	struct bio *bio;
 	struct timeval start;
 	struct timeval stop;
+	int mps;
 
 	printk(KERN_INFO "PM: Saving image data pages (%u pages) ...     ",
 		nr_to_write);
@@ -383,7 +387,8 @@ static int save_image(struct swap_map_handle *handle,
 		printk(KERN_CONT "\b\b\b\bdone\n");
 	else
 		printk(KERN_CONT "\n");
-	swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+	mps = swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+	write_speed = (mps < 256) ? (char) mps : 0;
 	return ret;
 }
 
@@ -545,6 +550,7 @@ static int load_image(struct swap_map_handle *handle,
 	struct bio *bio;
 	int err2;
 	unsigned nr_pages;
+	int mps;
 
 	printk(KERN_INFO "PM: Loading image data pages (%u pages) ...     ",
 		nr_to_read);
@@ -580,7 +586,8 @@ static int load_image(struct swap_map_handle *handle,
 			error = -ENODATA;
 	} else
 		printk("\n");
-	swsusp_show_speed(&start, &stop, nr_to_read, "Read");
+	mps = swsusp_show_speed(&start, &stop, nr_to_read, "Read");
+	read_speed = (mps < 256) ? mps : 0;
 	return error;
 }
 
@@ -646,6 +653,7 @@ int swsusp_check(void)
 			goto put;
 
 		if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
+			write_speed = swsusp_header->write_speed;
 			memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
 			/* Reset swap signature now */
 			error = hib_bio_write_page(swsusp_resume_block,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (2 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 02/23] Record & display i/o speed post resume Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 03/23] Hibernation: Swap iteration functions Nigel Cunningham
                   ` (49 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Record the speed at which the image is written and read, and
display it to the user post-resume.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/hibernate.c |   11 ++++++++++-
 kernel/power/power.h     |    3 ++-
 kernel/power/swap.c      |   14 +++++++++++---
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 6c9c9dc..0cd1f05 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
  *	@msg -		introductory message to print
  */
 
-void swsusp_show_speed(struct timeval *start, struct timeval *stop,
+int swsusp_show_speed(struct timeval *start, struct timeval *stop,
 			unsigned nr_pages, char *msg)
 {
 	s64 elapsed_centisecs64;
@@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
 			msg, k,
 			centisecs / 100, centisecs % 100,
 			kps / 1000, (kps % 1000) / 10);
+	return kps / 1000;
 }
 
 /**
@@ -648,6 +649,14 @@ int hibernate(void)
 			power_down();
 	} else {
 		pr_debug("PM: Image restored successfully.\n");
+		if (write_speed)
+			pr_debug("PM: Image written at %u MB/s.\n",
+					(u8) write_speed);
+		write_speed = 0;
+		if (read_speed)
+			pr_debug("PM: Image read at %u MB/s.\n",
+					(u8) read_speed);
+		read_speed = 0;
 	}
 
  Thaw:
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 03634be..22f8607 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
 extern int hibernation_restore(int platform_mode);
 extern int hibernation_platform_enter(void);
 
+extern char __nosavedata write_speed, read_speed;
 #else /* !CONFIG_HIBERNATION */
 
 static inline void hibernate_image_size_init(void) {}
@@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
 
 struct timeval;
 /* kernel/power/swsusp.c */
-extern void swsusp_show_speed(struct timeval *, struct timeval *,
+extern int swsusp_show_speed(struct timeval *, struct timeval *,
 				unsigned int, char *);
 
 #ifdef CONFIG_SUSPEND
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 3c01105..caf4db8 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -45,7 +45,8 @@ struct swap_map_page {
 };
 
 struct swsusp_header {
-	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
+	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
+	char write_speed;
 	sector_t image;
 	unsigned int flags;	/* Flags to pass to the "boot" kernel */
 	char	orig_sig[10];
@@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
 
 static unsigned short root_swap = 0xffff;
 struct block_device *hib_resume_bdev;
+char __nosavedata write_speed, read_speed;
 
 /*
  * Saving part
@@ -175,6 +177,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
 	    !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
 		memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
+		swsusp_header->write_speed = write_speed;
 		swsusp_header->image = handle->first_sector;
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
@@ -354,6 +357,7 @@ static int save_image(struct swap_map_handle *handle,
 	struct bio *bio;
 	struct timeval start;
 	struct timeval stop;
+	int mps;
 
 	printk(KERN_INFO "PM: Saving image data pages (%u pages) ...     ",
 		nr_to_write);
@@ -383,7 +387,8 @@ static int save_image(struct swap_map_handle *handle,
 		printk(KERN_CONT "\b\b\b\bdone\n");
 	else
 		printk(KERN_CONT "\n");
-	swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+	mps = swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+	write_speed = (mps < 256) ? (char) mps : 0;
 	return ret;
 }
 
@@ -545,6 +550,7 @@ static int load_image(struct swap_map_handle *handle,
 	struct bio *bio;
 	int err2;
 	unsigned nr_pages;
+	int mps;
 
 	printk(KERN_INFO "PM: Loading image data pages (%u pages) ...     ",
 		nr_to_read);
@@ -580,7 +586,8 @@ static int load_image(struct swap_map_handle *handle,
 			error = -ENODATA;
 	} else
 		printk("\n");
-	swsusp_show_speed(&start, &stop, nr_to_read, "Read");
+	mps = swsusp_show_speed(&start, &stop, nr_to_read, "Read");
+	read_speed = (mps < 256) ? mps : 0;
 	return error;
 }
 
@@ -646,6 +653,7 @@ int swsusp_check(void)
 			goto put;
 
 		if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
+			write_speed = swsusp_header->write_speed;
 			memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
 			/* Reset swap signature now */
 			error = hib_bio_write_page(swsusp_resume_block,
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 03/23] Hibernation: Swap iteration functions.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (4 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 03/23] Hibernation: Swap iteration functions Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-10-04 17:54   ` [linux-pm] " Pavel Machek
  2010-10-04 17:54   ` Pavel Machek
  2010-09-27  5:43 ` [PATCH 04/23] Hibernation: Move root_swap declaration Nigel Cunningham
                   ` (47 subsequent siblings)
  53 siblings, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add the data structure 'storage_position' and routines that allow
a caller to iterate over swap in sector order. Note that calling
reset_storage_pos only resets the position. next_swapdev_block
must also be called to get the address of the first (and subsequent
sectors).

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index caf4db8..4e5f6e3 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -68,6 +68,45 @@ struct swsusp_extent {
 
 static struct rb_root swsusp_extents = RB_ROOT;
 
+struct storage_position {
+	struct rb_node *node;
+	struct swsusp_extent *cur_ext;
+	unsigned long offset;
+};
+
+static struct storage_position pos;
+
+static void reset_storage_pos(void)
+{
+	pos.node = rb_first(&swsusp_extents);
+
+	if (!pos.node) {
+		pos.cur_ext = NULL;
+		pos.offset = 0;
+		return;
+	}
+
+	pos.cur_ext = container_of(pos.node, struct swsusp_extent, node);
+	pos.offset = pos.cur_ext->start;
+}
+
+static sector_t next_swapdev_block(void)
+{
+	if (!pos.node)
+		return 0;
+
+	if (pos.cur_ext->end >= pos.offset)
+		return pos.offset++;
+
+	pos.node = rb_next(pos.node);
+	if (!pos.node)
+		return 0;
+
+	pos.cur_ext = container_of(pos.node, struct swsusp_extent, node);
+	pos.offset = pos.cur_ext->start;
+	return pos.offset;
+}
+
 static int swsusp_extents_insert(unsigned long swap_offset)
 {
 	struct rb_node **new = &(swsusp_extents.rb_node);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 03/23] Hibernation: Swap iteration functions.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (3 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (48 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add the data structure 'storage_position' and routines that allow
a caller to iterate over swap in sector order. Note that calling
reset_storage_pos only resets the position. next_swapdev_block
must also be called to get the address of the first (and subsequent
sectors).

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index caf4db8..4e5f6e3 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -68,6 +68,45 @@ struct swsusp_extent {
 
 static struct rb_root swsusp_extents = RB_ROOT;
 
+struct storage_position {
+	struct rb_node *node;
+	struct swsusp_extent *cur_ext;
+	unsigned long offset;
+};
+
+static struct storage_position pos;
+
+static void reset_storage_pos(void)
+{
+	pos.node = rb_first(&swsusp_extents);
+
+	if (!pos.node) {
+		pos.cur_ext = NULL;
+		pos.offset = 0;
+		return;
+	}
+
+	pos.cur_ext = container_of(pos.node, struct swsusp_extent, node);
+	pos.offset = pos.cur_ext->start;
+}
+
+static sector_t next_swapdev_block(void)
+{
+	if (!pos.node)
+		return 0;
+
+	if (pos.cur_ext->end >= pos.offset)
+		return pos.offset++;
+
+	pos.node = rb_next(pos.node);
+	if (!pos.node)
+		return 0;
+
+	pos.cur_ext = container_of(pos.node, struct swsusp_extent, node);
+	pos.offset = pos.cur_ext->start;
+	return pos.offset;
+}
+
 static int swsusp_extents_insert(unsigned long swap_offset)
 {
 	struct rb_node **new = &(swsusp_extents.rb_node);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 04/23] Hibernation: Move root_swap declaration.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (6 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 04/23] Hibernation: Move root_swap declaration Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 05/23] Hibernation: Add mass swap allocation routine Nigel Cunningham
                   ` (45 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Move the declaration of root_swap in preparation for the
next patch.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 4e5f6e3..25090ed 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -44,6 +44,8 @@ struct swap_map_page {
 	sector_t next_swap;
 };
 
+static unsigned short root_swap = 0xffff;
+
 struct swsusp_header {
 	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
 	char write_speed;
@@ -199,7 +201,6 @@ int swsusp_swap_in_use(void)
  * General things
  */
 
-static unsigned short root_swap = 0xffff;
 struct block_device *hib_resume_bdev;
 char __nosavedata write_speed, read_speed;
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 04/23] Hibernation: Move root_swap declaration.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (5 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (46 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Move the declaration of root_swap in preparation for the
next patch.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 4e5f6e3..25090ed 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -44,6 +44,8 @@ struct swap_map_page {
 	sector_t next_swap;
 };
 
+static unsigned short root_swap = 0xffff;
+
 struct swsusp_header {
 	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
 	char write_speed;
@@ -199,7 +201,6 @@ int swsusp_swap_in_use(void)
  * General things
  */
 
-static unsigned short root_swap = 0xffff;
 struct block_device *hib_resume_bdev;
 char __nosavedata write_speed, read_speed;
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 05/23] Hibernation: Add mass swap allocation routine
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (7 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (44 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add a routine to allocate swap from a device en masse. This is only
for use by the in-kernel implementation, not uswsusp.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 25090ed..e597756 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -169,6 +169,19 @@ sector_t alloc_swapdev_block(int swap)
 	return 0;
 }
 
+int alloc_swapdev_blocks(int needed)
+{
+	int i;
+
+	for (i = 0; i < needed; i++) {
+		sector_t res = alloc_swapdev_block(root_swap);
+		if (!res)
+			break;
+	}
+
+	return i;
+}
+
 /**
  *	free_all_swap_pages - free swap pages allocated for saving image data.
  *	It also frees the extents used to register which swap entries had been
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 05/23] Hibernation: Add mass swap allocation routine
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (9 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 06/23] Hibernation: Switch to preallocating swap Nigel Cunningham
                   ` (42 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add a routine to allocate swap from a device en masse. This is only
for use by the in-kernel implementation, not uswsusp.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 25090ed..e597756 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -169,6 +169,19 @@ sector_t alloc_swapdev_block(int swap)
 	return 0;
 }
 
+int alloc_swapdev_blocks(int needed)
+{
+	int i;
+
+	for (i = 0; i < needed; i++) {
+		sector_t res = alloc_swapdev_block(root_swap);
+		if (!res)
+			break;
+	}
+
+	return i;
+}
+
 /**
  *	free_all_swap_pages - free swap pages allocated for saving image data.
  *	It also frees the extents used to register which swap entries had been
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 05/23] Hibernation: Add mass swap allocation routine
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (8 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 05/23] Hibernation: Add mass swap allocation routine Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (43 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add a routine to allocate swap from a device en masse. This is only
for use by the in-kernel implementation, not uswsusp.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 25090ed..e597756 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -169,6 +169,19 @@ sector_t alloc_swapdev_block(int swap)
 	return 0;
 }
 
+int alloc_swapdev_blocks(int needed)
+{
+	int i;
+
+	for (i = 0; i < needed; i++) {
+		sector_t res = alloc_swapdev_block(root_swap);
+		if (!res)
+			break;
+	}
+
+	return i;
+}
+
 /**
  *	free_all_swap_pages - free swap pages allocated for saving image data.
  *	It also frees the extents used to register which swap entries had been
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 06/23] Hibernation: Switch to preallocating swap.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (10 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (41 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Prior to this patch, we allocated swap as we were writing the image.
This patch changes things so that we instead allocate all the swap
we'll need prior to starting to write the image. It lays groundwork
for later patches that switch from doing I/O in batches.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   68 +++++++++++++++++++++++++++++---------------------
 1 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index e597756..4c08329 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -183,6 +183,34 @@ int alloc_swapdev_blocks(int needed)
 }
 
 /**
+ *	allocate_swap - Allocate enough swap to save the image.
+ *
+ *	Calculates the number of swap pages actually needed and seeks
+ *	to allocate that many from the resume partition. Returns TRUE
+ *	or FALSE to indicate whether we got enough storage.
+ */
+
+static int allocate_swap(unsigned int nr_pages, unsigned int flags)
+{
+	unsigned int free_swap = count_swap_pages(root_swap, 1);
+
+	nr_pages += compress_extra_pages(nr_pages, flags);
+	nr_pages += DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+
+	pr_debug("PM: Free swap pages: %u\n", free_swap);
+	if (free_swap < nr_pages)
+		return 0;
+
+	if (alloc_swapdev_blocks(nr_pages) < nr_pages) {
+		free_all_swap_pages(root_swap);
+		return 0;
+	}
+
+	reset_storage_pos();
+	return 1;
+}
+
+/**
  *	free_all_swap_pages - free swap pages allocated for saving image data.
  *	It also frees the extents used to register which swap entries had been
  *	allocated.
@@ -305,7 +333,8 @@ static void release_swap_writer(struct swap_map_handle *handle)
 	handle->cur = NULL;
 }
 
-static int get_swap_writer(struct swap_map_handle *handle)
+static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
+		unsigned int flags)
 {
 	int ret;
 
@@ -321,7 +350,12 @@ static int get_swap_writer(struct swap_map_handle *handle)
 		ret = -ENOMEM;
 		goto err_close;
 	}
-	handle->cur_swap = alloc_swapdev_block(root_swap);
+	if (!allocate_swap(pages, flags)) {
+		printk(KERN_ERR "PM: Not enough free swap\n");
+		ret = -ENOSPC;
+		goto err_close;
+	}
+	handle->cur_swap = next_swapdev_block();
 	if (!handle->cur_swap) {
 		ret = -ENOSPC;
 		goto err_rel;
@@ -344,7 +378,7 @@ int swap_write_page(struct swap_map_handle *handle, void *buf,
 
 	if (!handle->cur)
 		return -EINVAL;
-	offset = alloc_swapdev_block(root_swap);
+	offset = next_swapdev_block();
 	error = write_page(buf, offset, bio_chain);
 	if (error)
 		return error;
@@ -353,7 +387,7 @@ int swap_write_page(struct swap_map_handle *handle, void *buf,
 		error = hib_wait_on_bio_chain(bio_chain);
 		if (error)
 			goto out;
-		offset = alloc_swapdev_block(root_swap);
+		offset = next_swapdev_block();
 		if (!offset)
 			return -ENOSPC;
 		handle->cur->next_swap = offset;
@@ -447,25 +481,6 @@ static int save_image(struct swap_map_handle *handle,
 
 
 /**
- *	enough_swap - Make sure we have enough swap to save the image.
- *
- *	Returns TRUE or FALSE after checking the total amount of swap
- *	space avaiable from the resume partition.
- */
-
-static int enough_swap(unsigned int nr_pages, unsigned int flags)
-{
-	unsigned int free_swap = count_swap_pages(root_swap, 1);
-	unsigned int required;
-
-	pr_debug("PM: Free swap pages: %u\n", free_swap);
-
-	required = PAGES_FOR_IO + nr_pages +
-		compress_extra_pages(nr_pages, flags);
-	return free_swap > required;
-}
-
-/**
  *	swsusp_write - Write entire image and metadata.
  *	@flags: flags to pass to the "boot" kernel in the image header
  *
@@ -489,17 +504,12 @@ int swsusp_write(unsigned int flags)
 		return error;
 
 	pages = snapshot_get_image_size();
-	error = get_swap_writer(&handle);
+	error = get_swap_writer(&handle, pages, flags);
 	if (error) {
 		printk(KERN_ERR "PM: Cannot get swap writer\n");
 		compress_image_cleanup();
 		return error;
 	}
-	if (!enough_swap(pages, flags)) {
-		printk(KERN_ERR "PM: Not enough free swap\n");
-		error = -ENOSPC;
-		goto out_finish;
-	}
 	memset(&snapshot, 0, sizeof(struct snapshot_handle));
 	error = snapshot_read_next(&snapshot);
 	if (error < PAGE_SIZE) {
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 06/23] Hibernation: Switch to preallocating swap.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (11 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 06/23] Hibernation: Switch to preallocating swap Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 07/23] Hiberation: Fix speed display Nigel Cunningham
                   ` (40 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Prior to this patch, we allocated swap as we were writing the image.
This patch changes things so that we instead allocate all the swap
we'll need prior to starting to write the image. It lays groundwork
for later patches that switch from doing I/O in batches.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   68 +++++++++++++++++++++++++++++---------------------
 1 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index e597756..4c08329 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -183,6 +183,34 @@ int alloc_swapdev_blocks(int needed)
 }
 
 /**
+ *	allocate_swap - Allocate enough swap to save the image.
+ *
+ *	Calculates the number of swap pages actually needed and seeks
+ *	to allocate that many from the resume partition. Returns TRUE
+ *	or FALSE to indicate whether we got enough storage.
+ */
+
+static int allocate_swap(unsigned int nr_pages, unsigned int flags)
+{
+	unsigned int free_swap = count_swap_pages(root_swap, 1);
+
+	nr_pages += compress_extra_pages(nr_pages, flags);
+	nr_pages += DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+
+	pr_debug("PM: Free swap pages: %u\n", free_swap);
+	if (free_swap < nr_pages)
+		return 0;
+
+	if (alloc_swapdev_blocks(nr_pages) < nr_pages) {
+		free_all_swap_pages(root_swap);
+		return 0;
+	}
+
+	reset_storage_pos();
+	return 1;
+}
+
+/**
  *	free_all_swap_pages - free swap pages allocated for saving image data.
  *	It also frees the extents used to register which swap entries had been
  *	allocated.
@@ -305,7 +333,8 @@ static void release_swap_writer(struct swap_map_handle *handle)
 	handle->cur = NULL;
 }
 
-static int get_swap_writer(struct swap_map_handle *handle)
+static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
+		unsigned int flags)
 {
 	int ret;
 
@@ -321,7 +350,12 @@ static int get_swap_writer(struct swap_map_handle *handle)
 		ret = -ENOMEM;
 		goto err_close;
 	}
-	handle->cur_swap = alloc_swapdev_block(root_swap);
+	if (!allocate_swap(pages, flags)) {
+		printk(KERN_ERR "PM: Not enough free swap\n");
+		ret = -ENOSPC;
+		goto err_close;
+	}
+	handle->cur_swap = next_swapdev_block();
 	if (!handle->cur_swap) {
 		ret = -ENOSPC;
 		goto err_rel;
@@ -344,7 +378,7 @@ int swap_write_page(struct swap_map_handle *handle, void *buf,
 
 	if (!handle->cur)
 		return -EINVAL;
-	offset = alloc_swapdev_block(root_swap);
+	offset = next_swapdev_block();
 	error = write_page(buf, offset, bio_chain);
 	if (error)
 		return error;
@@ -353,7 +387,7 @@ int swap_write_page(struct swap_map_handle *handle, void *buf,
 		error = hib_wait_on_bio_chain(bio_chain);
 		if (error)
 			goto out;
-		offset = alloc_swapdev_block(root_swap);
+		offset = next_swapdev_block();
 		if (!offset)
 			return -ENOSPC;
 		handle->cur->next_swap = offset;
@@ -447,25 +481,6 @@ static int save_image(struct swap_map_handle *handle,
 
 
 /**
- *	enough_swap - Make sure we have enough swap to save the image.
- *
- *	Returns TRUE or FALSE after checking the total amount of swap
- *	space avaiable from the resume partition.
- */
-
-static int enough_swap(unsigned int nr_pages, unsigned int flags)
-{
-	unsigned int free_swap = count_swap_pages(root_swap, 1);
-	unsigned int required;
-
-	pr_debug("PM: Free swap pages: %u\n", free_swap);
-
-	required = PAGES_FOR_IO + nr_pages +
-		compress_extra_pages(nr_pages, flags);
-	return free_swap > required;
-}
-
-/**
  *	swsusp_write - Write entire image and metadata.
  *	@flags: flags to pass to the "boot" kernel in the image header
  *
@@ -489,17 +504,12 @@ int swsusp_write(unsigned int flags)
 		return error;
 
 	pages = snapshot_get_image_size();
-	error = get_swap_writer(&handle);
+	error = get_swap_writer(&handle, pages, flags);
 	if (error) {
 		printk(KERN_ERR "PM: Cannot get swap writer\n");
 		compress_image_cleanup();
 		return error;
 	}
-	if (!enough_swap(pages, flags)) {
-		printk(KERN_ERR "PM: Not enough free swap\n");
-		error = -ENOSPC;
-		goto out_finish;
-	}
 	memset(&snapshot, 0, sizeof(struct snapshot_handle));
 	error = snapshot_read_next(&snapshot);
 	if (error < PAGE_SIZE) {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 07/23] Hiberation: Fix speed display.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (12 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-10-04 17:51   ` Pavel Machek
  2010-10-04 17:51   ` [linux-pm] " Pavel Machek
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (39 subsequent siblings)
  53 siblings, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Correct the situation where, if an error occurs while writing an image,
the speed display still uses the number of pages that should have been
written, rather than the number of pages that were written.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 4c08329..fbda5cd 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -474,7 +474,7 @@ static int save_image(struct swap_map_handle *handle,
 		printk(KERN_CONT "\b\b\b\bdone\n");
 	else
 		printk(KERN_CONT "\n");
-	mps = swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+	mps = swsusp_show_speed(&start, &stop, nr_pages, "Wrote");
 	write_speed = (mps < 256) ? (char) mps : 0;
 	return ret;
 }
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 07/23] Hiberation: Fix speed display.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (13 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 07/23] Hiberation: Fix speed display Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 08/23] Hibernation: Generic extents support Nigel Cunningham
                   ` (38 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Correct the situation where, if an error occurs while writing an image,
the speed display still uses the number of pages that should have been
written, rather than the number of pages that were written.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 4c08329..fbda5cd 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -474,7 +474,7 @@ static int save_image(struct swap_map_handle *handle,
 		printk(KERN_CONT "\b\b\b\bdone\n");
 	else
 		printk(KERN_CONT "\n");
-	mps = swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+	mps = swsusp_show_speed(&start, &stop, nr_pages, "Wrote");
 	write_speed = (mps < 256) ? (char) mps : 0;
 	return ret;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 08/23] Hibernation: Generic extents support.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (15 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 08/23] Hibernation: Generic extents support Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-10-04 17:51   ` Pavel Machek
  2010-10-04 17:51   ` [linux-pm] " Pavel Machek
  2010-09-27  5:43 ` [PATCH 09/23] Hibernation: Iterate over sectors not swap entries Nigel Cunningham
                   ` (36 subsequent siblings)
  53 siblings, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Separate out the extent storage and manipulation into a separate
file and make them more generic, so we can also use extents for
recording what sectors are used and (later) support multiple
storage devices more easily.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/Makefile  |    2 +-
 kernel/power/extents.c |  125 ++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/extents.h |   35 +++++++++++++
 kernel/power/swap.c    |  117 +++++---------------------------------------
 4 files changed, 175 insertions(+), 104 deletions(-)
 create mode 100644 kernel/power/extents.c
 create mode 100644 kernel/power/extents.h

diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 2eb134d..f8f03e4 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
 obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
-				   block_io.o compress.o
+				   block_io.o compress.o extents.o
 obj-$(CONFIG_SUSPEND_NVS)	+= nvs.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/extents.c b/kernel/power/extents.c
new file mode 100644
index 0000000..172322d
--- /dev/null
+++ b/kernel/power/extents.c
@@ -0,0 +1,125 @@
+/*
+ * linux/kernel/power/extents.c
+ *
+ * This file provides functions for storing and using a series of
+ * extents.
+ *
+ * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz>
+ * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#include <linux/slab.h>
+#include "extents.h"
+
+int hib_extents_empty(struct hib_extent_state *pos)
+{
+	return RB_EMPTY_ROOT(&pos->root);
+}
+
+void hib_reset_extent_pos(struct hib_extent_state *pos)
+{
+	if (hib_extents_empty(pos))
+		return;
+
+	pos->node = rb_first(&pos->root);
+
+	if (!pos->node) {
+		pos->cur_ext = NULL;
+		pos->offset = 0;
+		return;
+	}
+
+	pos->cur_ext = container_of(pos->node, struct hib_extent, node);
+	pos->offset = pos->cur_ext->start;
+}
+
+unsigned long hib_extent_current(struct hib_extent_state *pos)
+{
+	return (pos->node) ? pos->offset : 0;
+}
+
+unsigned long hib_extent_next(struct hib_extent_state *pos)
+{
+	if (!pos->node)
+		return 0;
+
+	if (pos->cur_ext->end >= pos->offset)
+		return pos->offset++;
+
+	pos->node = rb_next(pos->node);
+	if (!pos->node)
+		return 0;
+
+	pos->cur_ext = container_of(pos->node, struct hib_extent, node);
+	pos->offset = pos->cur_ext->start;
+	return pos->offset;
+}
+
+int hib_extents_insert(struct hib_extent_state *pos, unsigned long value)
+{
+	struct rb_node **new = &(pos->root.rb_node);
+	struct rb_node *parent = NULL;
+	struct hib_extent *ext;
+
+	/* Figure out where to put the new node */
+	while (*new) {
+		ext = container_of(*new, struct hib_extent, node);
+		parent = *new;
+		if (value < ext->start) {
+			/* Try to merge */
+			if (value == ext->start - 1) {
+				ext->start--;
+				return 0;
+			}
+			new = &((*new)->rb_left);
+		} else if (value > ext->end) {
+			/* Try to merge */
+			if (value == ext->end + 1) {
+				ext->end++;
+				return 0;
+			}
+			new = &((*new)->rb_right);
+		} else {
+			/* It already is in the tree */
+			return -EINVAL;
+		}
+	}
+	/* Add the new node and rebalance the tree. */
+	ext = kzalloc(sizeof(struct hib_extent), GFP_KERNEL);
+	if (!ext)
+		return -ENOMEM;
+
+	ext->start = value;
+	ext->end = value;
+	rb_link_node(&ext->node, parent, new);
+	rb_insert_color(&ext->node, &pos->root);
+	pos->num_extents++;
+	return 0;
+}
+
+/**
+ *	free_all_swap_pages - free swap pages allocated for saving image data.
+ *	It also frees the extents used to register which swap entres had been
+ *	allocated.
+ */
+
+void hib_extents_clear(struct hib_extent_state *pos)
+{
+	struct rb_node *node;
+
+	if (hib_extents_empty(pos))
+		return;
+
+	while ((node = pos->root.rb_node)) {
+		struct hib_extent *ext;
+
+		ext = container_of(node, struct hib_extent, node);
+		rb_erase(node, &pos->root);
+		pos->num_extents--;
+		kfree(ext);
+	}
+}
diff --git a/kernel/power/extents.h b/kernel/power/extents.h
new file mode 100644
index 0000000..0b69b8e
--- /dev/null
+++ b/kernel/power/extents.h
@@ -0,0 +1,35 @@
+/*
+ * linux/kernel/power/extents.h
+ *
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#include <linux/rbtree.h>
+
+struct hib_extent {
+	struct rb_node node;
+	unsigned long start;
+	unsigned long end;
+};
+
+struct hib_extent_state {
+	/* Tree */
+	struct rb_root root;
+	int num_extents;
+
+	/* Current position */
+	struct rb_node *node;
+	struct hib_extent *cur_ext;
+	unsigned long offset;
+};
+
+
+void hib_reset_extent_pos(struct hib_extent_state *pos);
+unsigned long hib_extent_current(struct hib_extent_state *pos);
+unsigned long hib_extent_next(struct hib_extent_state *pos);
+int hib_extents_insert(struct hib_extent_state *pos, unsigned long value);
+void hib_extents_clear(struct hib_extent_state *pos);
+int hib_extents_empty(struct hib_extent_state *pos);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index fbda5cd..f16e973 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -14,11 +14,11 @@
 #include <linux/buffer_head.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
-#include <linux/slab.h>
 
 #include "power.h"
 #include "compress.h"
 #include "swap.h"
+#include "extents.h"
 
 #define SWSUSP_SIG	"S1SUSPEND"
 
@@ -57,97 +57,14 @@ struct swsusp_header {
 
 static struct swsusp_header *swsusp_header;
 
-/**
- *	The following functions are used for tracing the allocated
- *	swap pages, so that they can be freed in case of an error.
- */
-
-struct swsusp_extent {
-	struct rb_node node;
-	unsigned long start;
-	unsigned long end;
-};
-
-static struct rb_root swsusp_extents = RB_ROOT;
-
-struct storage_position {
-	struct rb_node *node;
-	struct swsusp_extent *cur_ext;
-	unsigned long offset;
-};
-
-static struct storage_position pos;
-
-static void reset_storage_pos(void)
-{
-	pos.node = rb_first(&swsusp_extents);
-
-	if (!pos.node) {
-		pos.cur_ext = NULL;
-		pos.offset = 0;
-		return;
-	}
-
-	pos.cur_ext = container_of(pos.node, struct swsusp_extent, node);
-	pos.offset = pos.cur_ext->start;
-}
+static struct hib_extent_state swap_extents;
 
 static sector_t next_swapdev_block(void)
 {
-	if (!pos.node)
-		return 0;
-
-	if (pos.cur_ext->end >= pos.offset)
-		return pos.offset++;
-
-	pos.node = rb_next(pos.node);
-	if (!pos.node)
-		return 0;
-
-	pos.cur_ext = container_of(pos.node, struct swsusp_extent, node);
-	pos.offset = pos.cur_ext->start;
-	return pos.offset;
-}
-
-static int swsusp_extents_insert(unsigned long swap_offset)
-{
-	struct rb_node **new = &(swsusp_extents.rb_node);
-	struct rb_node *parent = NULL;
-	struct swsusp_extent *ext;
-
-	/* Figure out where to put the new node */
-	while (*new) {
-		ext = container_of(*new, struct swsusp_extent, node);
-		parent = *new;
-		if (swap_offset < ext->start) {
-			/* Try to merge */
-			if (swap_offset == ext->start - 1) {
-				ext->start--;
-				return 0;
-			}
-			new = &((*new)->rb_left);
-		} else if (swap_offset > ext->end) {
-			/* Try to merge */
-			if (swap_offset == ext->end + 1) {
-				ext->end++;
-				return 0;
-			}
-			new = &((*new)->rb_right);
-		} else {
-			/* It already is in the tree */
-			return -EINVAL;
-		}
-	}
-	/* Add the new node and rebalance the tree. */
-	ext = kzalloc(sizeof(struct swsusp_extent), GFP_KERNEL);
-	if (!ext)
-		return -ENOMEM;
-
-	ext->start = swap_offset;
-	ext->end = swap_offset;
-	rb_link_node(&ext->node, parent, new);
-	rb_insert_color(&ext->node, &swsusp_extents);
-	return 0;
+	unsigned long res = hib_extent_next(&swap_extents);
+	if (res)
+		res = swapdev_block(root_swap, res);
+	return res;
 }
 
 /**
@@ -161,7 +78,7 @@ sector_t alloc_swapdev_block(int swap)
 
 	offset = swp_offset(get_swap_page_of_type(swap));
 	if (offset) {
-		if (swsusp_extents_insert(offset))
+		if (hib_extents_insert(&swap_extents, offset))
 			swap_free(swp_entry(swap, offset));
 		else
 			return swapdev_block(swap, offset);
@@ -206,7 +123,7 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 		return 0;
 	}
 
-	reset_storage_pos();
+	hib_reset_extent_pos(&swap_extents);
 	return 1;
 }
 
@@ -218,24 +135,18 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 
 void free_all_swap_pages(int swap)
 {
-	struct rb_node *node;
-
-	while ((node = swsusp_extents.rb_node)) {
-		struct swsusp_extent *ext;
-		unsigned long offset;
+	unsigned long offset;
 
-		ext = container_of(node, struct swsusp_extent, node);
-		rb_erase(node, &swsusp_extents);
-		for (offset = ext->start; offset <= ext->end; offset++)
-			swap_free(swp_entry(swap, offset));
+	hib_reset_extent_pos(&swap_extents);
+	while ((offset = hib_extent_next(&swap_extents)))
+		swap_free(swp_entry(swap, offset));
 
-		kfree(ext);
-	}
+	hib_extents_clear(&swap_extents);
 }
 
 int swsusp_swap_in_use(void)
 {
-	return (swsusp_extents.rb_node != NULL);
+	return (!hib_extents_empty(&swap_extents));
 }
 
 /*
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 08/23] Hibernation: Generic extents support.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (14 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (37 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Separate out the extent storage and manipulation into a separate
file and make them more generic, so we can also use extents for
recording what sectors are used and (later) support multiple
storage devices more easily.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/Makefile  |    2 +-
 kernel/power/extents.c |  125 ++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/extents.h |   35 +++++++++++++
 kernel/power/swap.c    |  117 +++++---------------------------------------
 4 files changed, 175 insertions(+), 104 deletions(-)
 create mode 100644 kernel/power/extents.c
 create mode 100644 kernel/power/extents.h

diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 2eb134d..f8f03e4 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
 obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
-				   block_io.o compress.o
+				   block_io.o compress.o extents.o
 obj-$(CONFIG_SUSPEND_NVS)	+= nvs.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/extents.c b/kernel/power/extents.c
new file mode 100644
index 0000000..172322d
--- /dev/null
+++ b/kernel/power/extents.c
@@ -0,0 +1,125 @@
+/*
+ * linux/kernel/power/extents.c
+ *
+ * This file provides functions for storing and using a series of
+ * extents.
+ *
+ * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz>
+ * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#include <linux/slab.h>
+#include "extents.h"
+
+int hib_extents_empty(struct hib_extent_state *pos)
+{
+	return RB_EMPTY_ROOT(&pos->root);
+}
+
+void hib_reset_extent_pos(struct hib_extent_state *pos)
+{
+	if (hib_extents_empty(pos))
+		return;
+
+	pos->node = rb_first(&pos->root);
+
+	if (!pos->node) {
+		pos->cur_ext = NULL;
+		pos->offset = 0;
+		return;
+	}
+
+	pos->cur_ext = container_of(pos->node, struct hib_extent, node);
+	pos->offset = pos->cur_ext->start;
+}
+
+unsigned long hib_extent_current(struct hib_extent_state *pos)
+{
+	return (pos->node) ? pos->offset : 0;
+}
+
+unsigned long hib_extent_next(struct hib_extent_state *pos)
+{
+	if (!pos->node)
+		return 0;
+
+	if (pos->cur_ext->end >= pos->offset)
+		return pos->offset++;
+
+	pos->node = rb_next(pos->node);
+	if (!pos->node)
+		return 0;
+
+	pos->cur_ext = container_of(pos->node, struct hib_extent, node);
+	pos->offset = pos->cur_ext->start;
+	return pos->offset;
+}
+
+int hib_extents_insert(struct hib_extent_state *pos, unsigned long value)
+{
+	struct rb_node **new = &(pos->root.rb_node);
+	struct rb_node *parent = NULL;
+	struct hib_extent *ext;
+
+	/* Figure out where to put the new node */
+	while (*new) {
+		ext = container_of(*new, struct hib_extent, node);
+		parent = *new;
+		if (value < ext->start) {
+			/* Try to merge */
+			if (value == ext->start - 1) {
+				ext->start--;
+				return 0;
+			}
+			new = &((*new)->rb_left);
+		} else if (value > ext->end) {
+			/* Try to merge */
+			if (value == ext->end + 1) {
+				ext->end++;
+				return 0;
+			}
+			new = &((*new)->rb_right);
+		} else {
+			/* It already is in the tree */
+			return -EINVAL;
+		}
+	}
+	/* Add the new node and rebalance the tree. */
+	ext = kzalloc(sizeof(struct hib_extent), GFP_KERNEL);
+	if (!ext)
+		return -ENOMEM;
+
+	ext->start = value;
+	ext->end = value;
+	rb_link_node(&ext->node, parent, new);
+	rb_insert_color(&ext->node, &pos->root);
+	pos->num_extents++;
+	return 0;
+}
+
+/**
+ *	free_all_swap_pages - free swap pages allocated for saving image data.
+ *	It also frees the extents used to register which swap entres had been
+ *	allocated.
+ */
+
+void hib_extents_clear(struct hib_extent_state *pos)
+{
+	struct rb_node *node;
+
+	if (hib_extents_empty(pos))
+		return;
+
+	while ((node = pos->root.rb_node)) {
+		struct hib_extent *ext;
+
+		ext = container_of(node, struct hib_extent, node);
+		rb_erase(node, &pos->root);
+		pos->num_extents--;
+		kfree(ext);
+	}
+}
diff --git a/kernel/power/extents.h b/kernel/power/extents.h
new file mode 100644
index 0000000..0b69b8e
--- /dev/null
+++ b/kernel/power/extents.h
@@ -0,0 +1,35 @@
+/*
+ * linux/kernel/power/extents.h
+ *
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#include <linux/rbtree.h>
+
+struct hib_extent {
+	struct rb_node node;
+	unsigned long start;
+	unsigned long end;
+};
+
+struct hib_extent_state {
+	/* Tree */
+	struct rb_root root;
+	int num_extents;
+
+	/* Current position */
+	struct rb_node *node;
+	struct hib_extent *cur_ext;
+	unsigned long offset;
+};
+
+
+void hib_reset_extent_pos(struct hib_extent_state *pos);
+unsigned long hib_extent_current(struct hib_extent_state *pos);
+unsigned long hib_extent_next(struct hib_extent_state *pos);
+int hib_extents_insert(struct hib_extent_state *pos, unsigned long value);
+void hib_extents_clear(struct hib_extent_state *pos);
+int hib_extents_empty(struct hib_extent_state *pos);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index fbda5cd..f16e973 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -14,11 +14,11 @@
 #include <linux/buffer_head.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
-#include <linux/slab.h>
 
 #include "power.h"
 #include "compress.h"
 #include "swap.h"
+#include "extents.h"
 
 #define SWSUSP_SIG	"S1SUSPEND"
 
@@ -57,97 +57,14 @@ struct swsusp_header {
 
 static struct swsusp_header *swsusp_header;
 
-/**
- *	The following functions are used for tracing the allocated
- *	swap pages, so that they can be freed in case of an error.
- */
-
-struct swsusp_extent {
-	struct rb_node node;
-	unsigned long start;
-	unsigned long end;
-};
-
-static struct rb_root swsusp_extents = RB_ROOT;
-
-struct storage_position {
-	struct rb_node *node;
-	struct swsusp_extent *cur_ext;
-	unsigned long offset;
-};
-
-static struct storage_position pos;
-
-static void reset_storage_pos(void)
-{
-	pos.node = rb_first(&swsusp_extents);
-
-	if (!pos.node) {
-		pos.cur_ext = NULL;
-		pos.offset = 0;
-		return;
-	}
-
-	pos.cur_ext = container_of(pos.node, struct swsusp_extent, node);
-	pos.offset = pos.cur_ext->start;
-}
+static struct hib_extent_state swap_extents;
 
 static sector_t next_swapdev_block(void)
 {
-	if (!pos.node)
-		return 0;
-
-	if (pos.cur_ext->end >= pos.offset)
-		return pos.offset++;
-
-	pos.node = rb_next(pos.node);
-	if (!pos.node)
-		return 0;
-
-	pos.cur_ext = container_of(pos.node, struct swsusp_extent, node);
-	pos.offset = pos.cur_ext->start;
-	return pos.offset;
-}
-
-static int swsusp_extents_insert(unsigned long swap_offset)
-{
-	struct rb_node **new = &(swsusp_extents.rb_node);
-	struct rb_node *parent = NULL;
-	struct swsusp_extent *ext;
-
-	/* Figure out where to put the new node */
-	while (*new) {
-		ext = container_of(*new, struct swsusp_extent, node);
-		parent = *new;
-		if (swap_offset < ext->start) {
-			/* Try to merge */
-			if (swap_offset == ext->start - 1) {
-				ext->start--;
-				return 0;
-			}
-			new = &((*new)->rb_left);
-		} else if (swap_offset > ext->end) {
-			/* Try to merge */
-			if (swap_offset == ext->end + 1) {
-				ext->end++;
-				return 0;
-			}
-			new = &((*new)->rb_right);
-		} else {
-			/* It already is in the tree */
-			return -EINVAL;
-		}
-	}
-	/* Add the new node and rebalance the tree. */
-	ext = kzalloc(sizeof(struct swsusp_extent), GFP_KERNEL);
-	if (!ext)
-		return -ENOMEM;
-
-	ext->start = swap_offset;
-	ext->end = swap_offset;
-	rb_link_node(&ext->node, parent, new);
-	rb_insert_color(&ext->node, &swsusp_extents);
-	return 0;
+	unsigned long res = hib_extent_next(&swap_extents);
+	if (res)
+		res = swapdev_block(root_swap, res);
+	return res;
 }
 
 /**
@@ -161,7 +78,7 @@ sector_t alloc_swapdev_block(int swap)
 
 	offset = swp_offset(get_swap_page_of_type(swap));
 	if (offset) {
-		if (swsusp_extents_insert(offset))
+		if (hib_extents_insert(&swap_extents, offset))
 			swap_free(swp_entry(swap, offset));
 		else
 			return swapdev_block(swap, offset);
@@ -206,7 +123,7 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 		return 0;
 	}
 
-	reset_storage_pos();
+	hib_reset_extent_pos(&swap_extents);
 	return 1;
 }
 
@@ -218,24 +135,18 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 
 void free_all_swap_pages(int swap)
 {
-	struct rb_node *node;
-
-	while ((node = swsusp_extents.rb_node)) {
-		struct swsusp_extent *ext;
-		unsigned long offset;
+	unsigned long offset;
 
-		ext = container_of(node, struct swsusp_extent, node);
-		rb_erase(node, &swsusp_extents);
-		for (offset = ext->start; offset <= ext->end; offset++)
-			swap_free(swp_entry(swap, offset));
+	hib_reset_extent_pos(&swap_extents);
+	while ((offset = hib_extent_next(&swap_extents)))
+		swap_free(swp_entry(swap, offset));
 
-		kfree(ext);
-	}
+	hib_extents_clear(&swap_extents);
 }
 
 int swsusp_swap_in_use(void)
 {
-	return (swsusp_extents.rb_node != NULL);
+	return (!hib_extents_empty(&swap_extents));
 }
 
 /*
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 09/23] Hibernation: Iterate over sectors not swap entries.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (17 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 09/23] Hibernation: Iterate over sectors not swap entries Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 10/23] Hibernation: Stop passing swap_map_handle struct Nigel Cunningham
                   ` (34 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Record sectors in extents when allocating storage, and use the
sector numbers instead of swap offsets as we write the image. If
we then store these sector extents at the start of the image (as
following patches will do), we can drop the index pages that are
interspersed with the image, do fully asynchronous I/O (which
should give a speed boost) and perhaps also remove some of the
duplication in the paths for reading and writing pages.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   25 ++++++++++---------------
 1 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index f16e973..819d21a 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -58,14 +58,7 @@ struct swsusp_header {
 static struct swsusp_header *swsusp_header;
 
 static struct hib_extent_state swap_extents;
-
-static sector_t next_swapdev_block(void)
-{
-	unsigned long res = hib_extent_next(&swap_extents);
-	if (res)
-		res = swapdev_block(root_swap, res);
-	return res;
-}
+static struct hib_extent_state sector_extents;
 
 /**
  *	alloc_swapdev_block - allocate a swap page and register that it has
@@ -74,14 +67,16 @@ static sector_t next_swapdev_block(void)
 
 sector_t alloc_swapdev_block(int swap)
 {
-	unsigned long offset;
+	unsigned long offset, sector;
 
 	offset = swp_offset(get_swap_page_of_type(swap));
 	if (offset) {
-		if (hib_extents_insert(&swap_extents, offset))
+		sector = swapdev_block(swap, offset);
+		if (hib_extents_insert(&swap_extents, offset) ||
+		    hib_extents_insert(&sector_extents, sector))
 			swap_free(swp_entry(swap, offset));
 		else
-			return swapdev_block(swap, offset);
+			return sector;
 	}
 	return 0;
 }
@@ -123,7 +118,7 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 		return 0;
 	}
 
-	hib_reset_extent_pos(&swap_extents);
+	hib_reset_extent_pos(&sector_extents);
 	return 1;
 }
 
@@ -266,7 +261,7 @@ static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
 		ret = -ENOSPC;
 		goto err_close;
 	}
-	handle->cur_swap = next_swapdev_block();
+	handle->cur_swap = hib_extent_next(&sector_extents);
 	if (!handle->cur_swap) {
 		ret = -ENOSPC;
 		goto err_rel;
@@ -289,7 +284,7 @@ int swap_write_page(struct swap_map_handle *handle, void *buf,
 
 	if (!handle->cur)
 		return -EINVAL;
-	offset = next_swapdev_block();
+	offset = hib_extent_next(&sector_extents);
 	error = write_page(buf, offset, bio_chain);
 	if (error)
 		return error;
@@ -298,7 +293,7 @@ int swap_write_page(struct swap_map_handle *handle, void *buf,
 		error = hib_wait_on_bio_chain(bio_chain);
 		if (error)
 			goto out;
-		offset = next_swapdev_block();
+		offset = hib_extent_next(&sector_extents);
 		if (!offset)
 			return -ENOSPC;
 		handle->cur->next_swap = offset;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 09/23] Hibernation: Iterate over sectors not swap entries.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (16 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (35 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Record sectors in extents when allocating storage, and use the
sector numbers instead of swap offsets as we write the image. If
we then store these sector extents at the start of the image (as
following patches will do), we can drop the index pages that are
interspersed with the image, do fully asynchronous I/O (which
should give a speed boost) and perhaps also remove some of the
duplication in the paths for reading and writing pages.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/swap.c |   25 ++++++++++---------------
 1 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index f16e973..819d21a 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -58,14 +58,7 @@ struct swsusp_header {
 static struct swsusp_header *swsusp_header;
 
 static struct hib_extent_state swap_extents;
-
-static sector_t next_swapdev_block(void)
-{
-	unsigned long res = hib_extent_next(&swap_extents);
-	if (res)
-		res = swapdev_block(root_swap, res);
-	return res;
-}
+static struct hib_extent_state sector_extents;
 
 /**
  *	alloc_swapdev_block - allocate a swap page and register that it has
@@ -74,14 +67,16 @@ static sector_t next_swapdev_block(void)
 
 sector_t alloc_swapdev_block(int swap)
 {
-	unsigned long offset;
+	unsigned long offset, sector;
 
 	offset = swp_offset(get_swap_page_of_type(swap));
 	if (offset) {
-		if (hib_extents_insert(&swap_extents, offset))
+		sector = swapdev_block(swap, offset);
+		if (hib_extents_insert(&swap_extents, offset) ||
+		    hib_extents_insert(&sector_extents, sector))
 			swap_free(swp_entry(swap, offset));
 		else
-			return swapdev_block(swap, offset);
+			return sector;
 	}
 	return 0;
 }
@@ -123,7 +118,7 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 		return 0;
 	}
 
-	hib_reset_extent_pos(&swap_extents);
+	hib_reset_extent_pos(&sector_extents);
 	return 1;
 }
 
@@ -266,7 +261,7 @@ static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
 		ret = -ENOSPC;
 		goto err_close;
 	}
-	handle->cur_swap = next_swapdev_block();
+	handle->cur_swap = hib_extent_next(&sector_extents);
 	if (!handle->cur_swap) {
 		ret = -ENOSPC;
 		goto err_rel;
@@ -289,7 +284,7 @@ int swap_write_page(struct swap_map_handle *handle, void *buf,
 
 	if (!handle->cur)
 		return -EINVAL;
-	offset = next_swapdev_block();
+	offset = hib_extent_next(&sector_extents);
 	error = write_page(buf, offset, bio_chain);
 	if (error)
 		return error;
@@ -298,7 +293,7 @@ int swap_write_page(struct swap_map_handle *handle, void *buf,
 		error = hib_wait_on_bio_chain(bio_chain);
 		if (error)
 			goto out;
-		offset = next_swapdev_block();
+		offset = hib_extent_next(&sector_extents);
 		if (!offset)
 			return -ENOSPC;
 		handle->cur->next_swap = offset;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 10/23] Hibernation: Stop passing swap_map_handle struct
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (19 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 10/23] Hibernation: Stop passing swap_map_handle struct Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 11/23] Hibernation: Stop passing bio_chain around Nigel Cunningham
                   ` (32 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Stop passing the swap_map_handle struct around. It's a local (to the
file) variable and continuing to pass it around will create ugliness
as I work to disentangle swap specific functions from block i/o and
put them in separate files.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/compress.c |   29 ++++-----
 kernel/power/compress.h |   11 +---
 kernel/power/swap.c     |  155 ++++++++++++++++++++++++-----------------------
 kernel/power/swap.h     |   18 +-----
 4 files changed, 97 insertions(+), 116 deletions(-)

diff --git a/kernel/power/compress.c b/kernel/power/compress.c
index 45725ea..b8b8c63 100644
--- a/kernel/power/compress.c
+++ b/kernel/power/compress.c
@@ -78,7 +78,7 @@ int compress_image_init(void)
 	return 0;
 }
 
-static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
+static int compress_and_write(struct bio **bio)
 {
 	int ret;
 
@@ -111,7 +111,7 @@ static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
 	for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
 		memcpy(page, cmp + off, PAGE_SIZE);
 
-		ret = swap_write_page(handle, page, bio);
+		ret = swap_write_page(page, bio);
 		if (ret)
 			return ret;
 	}
@@ -120,32 +120,30 @@ static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
 	return 0;
 }
 
-int compress_write(struct swap_map_handle *handle, char *buf, struct bio **bio,
-		int flags)
+int compress_write(char *buf, struct bio **bio, int flags)
 {
 	int ret = 0;
 
 	if (flags & SF_NOCOMPRESS_MODE)
-		return swap_write_page(handle, buf, bio);
+		return swap_write_page(buf, bio);
 
 	if (off == LZO_UNC_SIZE)
-		ret = compress_and_write(handle, bio);
+		ret = compress_and_write(bio);
 
 	memcpy(unc + off, buf, PAGE_SIZE);
 	off += PAGE_SIZE;
 	return ret;
 }
 
-void compress_write_finish(struct swap_map_handle *handle, struct bio **bio,
-		int flags)
+void compress_write_finish(struct bio **bio, int flags)
 {
 	if (!(flags & SF_NOCOMPRESS_MODE))
-		compress_and_write(handle, bio);
+		compress_and_write(bio);
 }
 
-static int read_and_decompress(struct swap_map_handle *handle)
+static int read_and_decompress(void)
 {
-	int error = swap_read_page(handle, page, NULL), off;
+	int error = swap_read_page(page, NULL), off;
 	cmp_len = *(size_t *)page;
 
 	if (unlikely(!cmp_len ||
@@ -156,7 +154,7 @@ static int read_and_decompress(struct swap_map_handle *handle)
 
 	memcpy(cmp, page, PAGE_SIZE);
 	for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-		error = swap_read_page(handle, page, NULL); /* sync */
+		error = swap_read_page(page, NULL); /* sync */
 		if (error)
 			return error;
 
@@ -181,16 +179,15 @@ static int read_and_decompress(struct swap_map_handle *handle)
 	return 0;
 }
 
-int compress_read(struct swap_map_handle *handle, char *buf, struct bio **bio,
-		int flags)
+int compress_read(char *buf, struct bio **bio, int flags)
 {
 	int ret = 0;
 
 	if (flags & SF_NOCOMPRESS_MODE)
-		return swap_read_page(handle, buf, bio);
+		return swap_read_page(buf, bio);
 
 	if (!off) {
-		ret = read_and_decompress(handle);
+		ret = read_and_decompress();
 		if (ret)
 			return ret;
 	}
diff --git a/kernel/power/compress.h b/kernel/power/compress.h
index 32abfc3..a25f673 100644
--- a/kernel/power/compress.h
+++ b/kernel/power/compress.h
@@ -10,14 +10,9 @@
  *
  */
 
-struct swap_map_handle;
-
 int compress_image_init(void);
 void compress_image_cleanup(void);
-int compress_write(struct swap_map_handle *handle, char *page, struct bio **bio,
-		int flags);
-void compress_write_finish(struct swap_map_handle *handle, struct bio **bio,
-		int flags);
-int compress_read(struct swap_map_handle *handle, char *page, struct bio **bio,
-		int flags);
+int compress_write(char *page, struct bio **bio, int flags);
+void compress_write_finish(struct bio **bio, int flags);
+int compress_read(char *page, struct bio **bio, int flags);
 unsigned int compress_extra_pages(unsigned int base, unsigned int flags);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 819d21a..7340314 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -44,6 +44,20 @@ struct swap_map_page {
 	sector_t next_swap;
 };
 
+/**
+ *	The swap_map_handle structure is used for handling swap in
+ *	a file-alike way
+ */
+
+struct swap_map_handle {
+	struct swap_map_page *cur;
+	sector_t cur_swap;
+	sector_t first_sector;
+	unsigned int k;
+};
+
+static struct swap_map_handle handle;
+
 static unsigned short root_swap = 0xffff;
 
 struct swsusp_header {
@@ -155,7 +169,7 @@ char __nosavedata write_speed, read_speed;
  * Saving part
  */
 
-static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
+static int mark_swapfiles(unsigned int flags)
 {
 	int error;
 
@@ -165,7 +179,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
 		memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
 		swsusp_header->write_speed = write_speed;
-		swsusp_header->image = handle->first_sector;
+		swsusp_header->image = handle.first_sector;
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
 					swsusp_header, NULL);
@@ -232,15 +246,14 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
 	return hib_bio_write_page(offset, src, bio_chain);
 }
 
-static void release_swap_writer(struct swap_map_handle *handle)
+static void release_swap_writer(void)
 {
-	if (handle->cur)
-		free_page((unsigned long)handle->cur);
-	handle->cur = NULL;
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
 }
 
-static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
-		unsigned int flags)
+static int get_swap_writer(unsigned long pages, unsigned int flags)
 {
 	int ret;
 
@@ -251,8 +264,8 @@ static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
 					"swapon -a.\n");
 		return ret;
 	}
-	handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
-	if (!handle->cur) {
+	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
+	if (!handle.cur) {
 		ret = -ENOMEM;
 		goto err_close;
 	}
@@ -261,74 +274,72 @@ static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
 		ret = -ENOSPC;
 		goto err_close;
 	}
-	handle->cur_swap = hib_extent_next(&sector_extents);
-	if (!handle->cur_swap) {
+	handle.cur_swap = hib_extent_next(&sector_extents);
+	if (!handle.cur_swap) {
 		ret = -ENOSPC;
 		goto err_rel;
 	}
-	handle->k = 0;
-	handle->first_sector = handle->cur_swap;
+	handle.k = 0;
+	handle.first_sector = handle.cur_swap;
 	return 0;
 err_rel:
-	release_swap_writer(handle);
+	release_swap_writer();
 err_close:
 	swsusp_close(FMODE_WRITE);
 	return ret;
 }
 
-int swap_write_page(struct swap_map_handle *handle, void *buf,
-				struct bio **bio_chain)
+int swap_write_page(void *buf, struct bio **bio_chain)
 {
 	int error = 0;
 	sector_t offset;
 
-	if (!handle->cur)
+	if (!handle.cur)
 		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
 	error = write_page(buf, offset, bio_chain);
 	if (error)
 		return error;
-	handle->cur->entries[handle->k++] = offset;
-	if (handle->k >= MAP_PAGE_ENTRIES) {
+	handle.cur->entries[handle.k++] = offset;
+	if (handle.k >= MAP_PAGE_ENTRIES) {
 		error = hib_wait_on_bio_chain(bio_chain);
 		if (error)
 			goto out;
 		offset = hib_extent_next(&sector_extents);
 		if (!offset)
 			return -ENOSPC;
-		handle->cur->next_swap = offset;
-		error = write_page(handle->cur, handle->cur_swap, NULL);
+		handle.cur->next_swap = offset;
+		error = write_page(handle.cur, handle.cur_swap, NULL);
 		if (error)
 			goto out;
-		memset(handle->cur, 0, PAGE_SIZE);
-		handle->cur_swap = offset;
-		handle->k = 0;
+		memset(handle.cur, 0, PAGE_SIZE);
+		handle.cur_swap = offset;
+		handle.k = 0;
 	}
  out:
 	return error;
 }
 
-static int flush_swap_writer(struct swap_map_handle *handle)
+static int flush_swap_writer(void)
 {
-	if (handle->cur && handle->cur_swap)
-		return write_page(handle->cur, handle->cur_swap, NULL);
+	if (handle.cur && handle.cur_swap)
+		return write_page(handle.cur, handle.cur_swap, NULL);
 	else
 		return -EINVAL;
 }
 
-static int swap_writer_finish(struct swap_map_handle *handle,
-		unsigned int flags, int error)
+static int swap_writer_finish(unsigned int flags, int error)
 {
 	if (!error) {
-		flush_swap_writer(handle);
+		flush_swap_writer();
 		printk(KERN_INFO "PM: S");
-		error = mark_swapfiles(handle, flags);
+		error = mark_swapfiles(flags);
 		printk("|\n");
 	}
 
 	if (error)
 		free_all_swap_pages(root_swap);
-	release_swap_writer(handle);
+	release_swap_writer();
 	swsusp_close(FMODE_WRITE);
 
 	return error;
@@ -338,8 +349,7 @@ static int swap_writer_finish(struct swap_map_handle *handle,
  *	save_image - save the suspend image data
  */
 
-static int save_image(struct swap_map_handle *handle,
-                      struct snapshot_handle *snapshot,
+static int save_image(struct snapshot_handle *snapshot,
                       unsigned int nr_to_write,
 		      int flags)
 {
@@ -364,14 +374,14 @@ static int save_image(struct swap_map_handle *handle,
 		ret = snapshot_read_next(snapshot);
 		if (ret <= 0)
 			break;
-		ret = compress_write(handle, data_of(*snapshot), &bio, flags);
+		ret = compress_write(data_of(*snapshot), &bio, flags);
 		if (ret)
 			break;
 		if (!(nr_pages % m))
 			printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	compress_write_finish(handle, &bio, flags);
+	compress_write_finish(&bio, flags);
 	err2 = hib_wait_on_bio_chain(&bio);
 	do_gettimeofday(&stop);
 	if (!ret)
@@ -398,7 +408,6 @@ static int save_image(struct swap_map_handle *handle,
 
 int swsusp_write(unsigned int flags)
 {
-	struct swap_map_handle handle;
 	struct snapshot_handle snapshot;
 	struct swsusp_info *header;
 	unsigned long pages;
@@ -410,7 +419,7 @@ int swsusp_write(unsigned int flags)
 		return error;
 
 	pages = snapshot_get_image_size();
-	error = get_swap_writer(&handle, pages, flags);
+	error = get_swap_writer(pages, flags);
 	if (error) {
 		printk(KERN_ERR "PM: Cannot get swap writer\n");
 		compress_image_cleanup();
@@ -425,12 +434,12 @@ int swsusp_write(unsigned int flags)
 		goto out_finish;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = swap_write_page(&handle, header, NULL);
+	error = swap_write_page(header, NULL);
 	if (!error)
-		error = save_image(&handle, &snapshot, pages - 1, flags);
+		error = save_image(&snapshot, pages - 1, flags);
 out_finish:
 	compress_image_cleanup();
-	error = swap_writer_finish(&handle, flags, error);
+	error = swap_writer_finish(flags, error);
 	return error;
 }
 
@@ -439,15 +448,14 @@ out_finish:
  *	in a file-alike way
  */
 
-static void release_swap_reader(struct swap_map_handle *handle)
+static void release_swap_reader(void)
 {
-	if (handle->cur)
-		free_page((unsigned long)handle->cur);
-	handle->cur = NULL;
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
 }
 
-static int get_swap_reader(struct swap_map_handle *handle,
-		unsigned int *flags_p)
+static int get_swap_reader(unsigned int *flags_p)
 {
 	int error;
 
@@ -456,48 +464,47 @@ static int get_swap_reader(struct swap_map_handle *handle,
 	if (!swsusp_header->image) /* how can this happen? */
 		return -EINVAL;
 
-	handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
-	if (!handle->cur)
+	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
+	if (!handle.cur)
 		return -ENOMEM;
 
-	error = hib_bio_read_page(swsusp_header->image, handle->cur, NULL);
+	error = hib_bio_read_page(swsusp_header->image, handle.cur, NULL);
 	if (error) {
-		release_swap_reader(handle);
+		release_swap_reader();
 		return error;
 	}
-	handle->k = 0;
+	handle.k = 0;
 	return 0;
 }
 
-int swap_read_page(struct swap_map_handle *handle, void *buf,
-				struct bio **bio_chain)
+int swap_read_page(void *buf, struct bio **bio_chain)
 {
 	sector_t offset;
 	int error;
 
-	if (!handle->cur)
+	if (!handle.cur)
 		return -EINVAL;
-	offset = handle->cur->entries[handle->k];
+	offset = handle.cur->entries[handle.k];
 	if (!offset)
 		return -EFAULT;
 	error = hib_bio_read_page(offset, buf, bio_chain);
 	if (error)
 		return error;
-	if (++handle->k >= MAP_PAGE_ENTRIES) {
+	if (++handle.k >= MAP_PAGE_ENTRIES) {
 		error = hib_wait_on_bio_chain(bio_chain);
-		handle->k = 0;
-		offset = handle->cur->next_swap;
+		handle.k = 0;
+		offset = handle.cur->next_swap;
 		if (!offset)
-			release_swap_reader(handle);
+			release_swap_reader();
 		else if (!error)
-			error = hib_bio_read_page(offset, handle->cur, NULL);
+			error = hib_bio_read_page(offset, handle.cur, NULL);
 	}
 	return error;
 }
 
-static int swap_reader_finish(struct swap_map_handle *handle)
+static int swap_reader_finish(void)
 {
-	release_swap_reader(handle);
+	release_swap_reader();
 
 	return 0;
 }
@@ -508,9 +515,8 @@ static int swap_reader_finish(struct swap_map_handle *handle)
  *	(assume there are @nr_pages pages to load)
  */
 
-static int load_image(struct swap_map_handle *handle,
-                      struct snapshot_handle *snapshot,
-                      unsigned int nr_to_read, int flags)
+static int load_image(struct snapshot_handle *snapshot,
+		unsigned int nr_to_read, int flags)
 {
 	unsigned int m;
 	int error = 0;
@@ -533,7 +539,7 @@ static int load_image(struct swap_map_handle *handle,
 		error = snapshot_write_next(snapshot);
 		if (error <= 0)
 			break;
-		error = compress_read(handle, data_of(*snapshot), &bio, flags);
+		error = compress_read(data_of(*snapshot), &bio, flags);
 		if (error)
 			break;
 		if (snapshot->sync_read)
@@ -569,7 +575,6 @@ static int load_image(struct swap_map_handle *handle,
 int swsusp_read(unsigned int *flags_p)
 {
 	int error = 0;
-	struct swap_map_handle handle;
 	struct snapshot_handle snapshot;
 	struct swsusp_info *header;
 
@@ -585,16 +590,14 @@ int swsusp_read(unsigned int *flags_p)
 		return error < 0 ? error : -EFAULT;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = get_swap_reader(&handle, flags_p);
+	error = get_swap_reader(flags_p);
 	if (error)
 		goto end;
 	if (!error)
-		error = swap_read_page(&handle, header, NULL);
-	if (!error) {
-		error = load_image(&handle, &snapshot, header->pages - 1,
-				*flags_p);
-	}
-	swap_reader_finish(&handle);
+		error = swap_read_page(header, NULL);
+	if (!error)
+		error = load_image(&snapshot, header->pages - 1, *flags_p);
+	swap_reader_finish();
 end:
 	compress_image_cleanup();
 	if (!error)
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
index e9ad377..7d109ad 100644
--- a/kernel/power/swap.h
+++ b/kernel/power/swap.h
@@ -10,19 +10,5 @@
  *
  */
 
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	sector_t cur_swap;
-	sector_t first_sector;
-	unsigned int k;
-};
-
-int swap_write_page(struct swap_map_handle *handle, void *buf,
-				struct bio **bio_chain);
-int swap_read_page(struct swap_map_handle *handle, void *buf,
-				struct bio **bio_chain);
+int swap_write_page(void *buf, struct bio **bio_chain);
+int swap_read_page(void *buf, struct bio **bio_chain);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 10/23] Hibernation: Stop passing swap_map_handle struct
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (18 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (33 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Stop passing the swap_map_handle struct around. It's a local (to the
file) variable and continuing to pass it around will create ugliness
as I work to disentangle swap specific functions from block i/o and
put them in separate files.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/compress.c |   29 ++++-----
 kernel/power/compress.h |   11 +---
 kernel/power/swap.c     |  155 ++++++++++++++++++++++++-----------------------
 kernel/power/swap.h     |   18 +-----
 4 files changed, 97 insertions(+), 116 deletions(-)

diff --git a/kernel/power/compress.c b/kernel/power/compress.c
index 45725ea..b8b8c63 100644
--- a/kernel/power/compress.c
+++ b/kernel/power/compress.c
@@ -78,7 +78,7 @@ int compress_image_init(void)
 	return 0;
 }
 
-static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
+static int compress_and_write(struct bio **bio)
 {
 	int ret;
 
@@ -111,7 +111,7 @@ static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
 	for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
 		memcpy(page, cmp + off, PAGE_SIZE);
 
-		ret = swap_write_page(handle, page, bio);
+		ret = swap_write_page(page, bio);
 		if (ret)
 			return ret;
 	}
@@ -120,32 +120,30 @@ static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
 	return 0;
 }
 
-int compress_write(struct swap_map_handle *handle, char *buf, struct bio **bio,
-		int flags)
+int compress_write(char *buf, struct bio **bio, int flags)
 {
 	int ret = 0;
 
 	if (flags & SF_NOCOMPRESS_MODE)
-		return swap_write_page(handle, buf, bio);
+		return swap_write_page(buf, bio);
 
 	if (off == LZO_UNC_SIZE)
-		ret = compress_and_write(handle, bio);
+		ret = compress_and_write(bio);
 
 	memcpy(unc + off, buf, PAGE_SIZE);
 	off += PAGE_SIZE;
 	return ret;
 }
 
-void compress_write_finish(struct swap_map_handle *handle, struct bio **bio,
-		int flags)
+void compress_write_finish(struct bio **bio, int flags)
 {
 	if (!(flags & SF_NOCOMPRESS_MODE))
-		compress_and_write(handle, bio);
+		compress_and_write(bio);
 }
 
-static int read_and_decompress(struct swap_map_handle *handle)
+static int read_and_decompress(void)
 {
-	int error = swap_read_page(handle, page, NULL), off;
+	int error = swap_read_page(page, NULL), off;
 	cmp_len = *(size_t *)page;
 
 	if (unlikely(!cmp_len ||
@@ -156,7 +154,7 @@ static int read_and_decompress(struct swap_map_handle *handle)
 
 	memcpy(cmp, page, PAGE_SIZE);
 	for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-		error = swap_read_page(handle, page, NULL); /* sync */
+		error = swap_read_page(page, NULL); /* sync */
 		if (error)
 			return error;
 
@@ -181,16 +179,15 @@ static int read_and_decompress(struct swap_map_handle *handle)
 	return 0;
 }
 
-int compress_read(struct swap_map_handle *handle, char *buf, struct bio **bio,
-		int flags)
+int compress_read(char *buf, struct bio **bio, int flags)
 {
 	int ret = 0;
 
 	if (flags & SF_NOCOMPRESS_MODE)
-		return swap_read_page(handle, buf, bio);
+		return swap_read_page(buf, bio);
 
 	if (!off) {
-		ret = read_and_decompress(handle);
+		ret = read_and_decompress();
 		if (ret)
 			return ret;
 	}
diff --git a/kernel/power/compress.h b/kernel/power/compress.h
index 32abfc3..a25f673 100644
--- a/kernel/power/compress.h
+++ b/kernel/power/compress.h
@@ -10,14 +10,9 @@
  *
  */
 
-struct swap_map_handle;
-
 int compress_image_init(void);
 void compress_image_cleanup(void);
-int compress_write(struct swap_map_handle *handle, char *page, struct bio **bio,
-		int flags);
-void compress_write_finish(struct swap_map_handle *handle, struct bio **bio,
-		int flags);
-int compress_read(struct swap_map_handle *handle, char *page, struct bio **bio,
-		int flags);
+int compress_write(char *page, struct bio **bio, int flags);
+void compress_write_finish(struct bio **bio, int flags);
+int compress_read(char *page, struct bio **bio, int flags);
 unsigned int compress_extra_pages(unsigned int base, unsigned int flags);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 819d21a..7340314 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -44,6 +44,20 @@ struct swap_map_page {
 	sector_t next_swap;
 };
 
+/**
+ *	The swap_map_handle structure is used for handling swap in
+ *	a file-alike way
+ */
+
+struct swap_map_handle {
+	struct swap_map_page *cur;
+	sector_t cur_swap;
+	sector_t first_sector;
+	unsigned int k;
+};
+
+static struct swap_map_handle handle;
+
 static unsigned short root_swap = 0xffff;
 
 struct swsusp_header {
@@ -155,7 +169,7 @@ char __nosavedata write_speed, read_speed;
  * Saving part
  */
 
-static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
+static int mark_swapfiles(unsigned int flags)
 {
 	int error;
 
@@ -165,7 +179,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
 		memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
 		swsusp_header->write_speed = write_speed;
-		swsusp_header->image = handle->first_sector;
+		swsusp_header->image = handle.first_sector;
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
 					swsusp_header, NULL);
@@ -232,15 +246,14 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
 	return hib_bio_write_page(offset, src, bio_chain);
 }
 
-static void release_swap_writer(struct swap_map_handle *handle)
+static void release_swap_writer(void)
 {
-	if (handle->cur)
-		free_page((unsigned long)handle->cur);
-	handle->cur = NULL;
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
 }
 
-static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
-		unsigned int flags)
+static int get_swap_writer(unsigned long pages, unsigned int flags)
 {
 	int ret;
 
@@ -251,8 +264,8 @@ static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
 					"swapon -a.\n");
 		return ret;
 	}
-	handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
-	if (!handle->cur) {
+	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
+	if (!handle.cur) {
 		ret = -ENOMEM;
 		goto err_close;
 	}
@@ -261,74 +274,72 @@ static int get_swap_writer(struct swap_map_handle *handle, unsigned long pages,
 		ret = -ENOSPC;
 		goto err_close;
 	}
-	handle->cur_swap = hib_extent_next(&sector_extents);
-	if (!handle->cur_swap) {
+	handle.cur_swap = hib_extent_next(&sector_extents);
+	if (!handle.cur_swap) {
 		ret = -ENOSPC;
 		goto err_rel;
 	}
-	handle->k = 0;
-	handle->first_sector = handle->cur_swap;
+	handle.k = 0;
+	handle.first_sector = handle.cur_swap;
 	return 0;
 err_rel:
-	release_swap_writer(handle);
+	release_swap_writer();
 err_close:
 	swsusp_close(FMODE_WRITE);
 	return ret;
 }
 
-int swap_write_page(struct swap_map_handle *handle, void *buf,
-				struct bio **bio_chain)
+int swap_write_page(void *buf, struct bio **bio_chain)
 {
 	int error = 0;
 	sector_t offset;
 
-	if (!handle->cur)
+	if (!handle.cur)
 		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
 	error = write_page(buf, offset, bio_chain);
 	if (error)
 		return error;
-	handle->cur->entries[handle->k++] = offset;
-	if (handle->k >= MAP_PAGE_ENTRIES) {
+	handle.cur->entries[handle.k++] = offset;
+	if (handle.k >= MAP_PAGE_ENTRIES) {
 		error = hib_wait_on_bio_chain(bio_chain);
 		if (error)
 			goto out;
 		offset = hib_extent_next(&sector_extents);
 		if (!offset)
 			return -ENOSPC;
-		handle->cur->next_swap = offset;
-		error = write_page(handle->cur, handle->cur_swap, NULL);
+		handle.cur->next_swap = offset;
+		error = write_page(handle.cur, handle.cur_swap, NULL);
 		if (error)
 			goto out;
-		memset(handle->cur, 0, PAGE_SIZE);
-		handle->cur_swap = offset;
-		handle->k = 0;
+		memset(handle.cur, 0, PAGE_SIZE);
+		handle.cur_swap = offset;
+		handle.k = 0;
 	}
  out:
 	return error;
 }
 
-static int flush_swap_writer(struct swap_map_handle *handle)
+static int flush_swap_writer(void)
 {
-	if (handle->cur && handle->cur_swap)
-		return write_page(handle->cur, handle->cur_swap, NULL);
+	if (handle.cur && handle.cur_swap)
+		return write_page(handle.cur, handle.cur_swap, NULL);
 	else
 		return -EINVAL;
 }
 
-static int swap_writer_finish(struct swap_map_handle *handle,
-		unsigned int flags, int error)
+static int swap_writer_finish(unsigned int flags, int error)
 {
 	if (!error) {
-		flush_swap_writer(handle);
+		flush_swap_writer();
 		printk(KERN_INFO "PM: S");
-		error = mark_swapfiles(handle, flags);
+		error = mark_swapfiles(flags);
 		printk("|\n");
 	}
 
 	if (error)
 		free_all_swap_pages(root_swap);
-	release_swap_writer(handle);
+	release_swap_writer();
 	swsusp_close(FMODE_WRITE);
 
 	return error;
@@ -338,8 +349,7 @@ static int swap_writer_finish(struct swap_map_handle *handle,
  *	save_image - save the suspend image data
  */
 
-static int save_image(struct swap_map_handle *handle,
-                      struct snapshot_handle *snapshot,
+static int save_image(struct snapshot_handle *snapshot,
                       unsigned int nr_to_write,
 		      int flags)
 {
@@ -364,14 +374,14 @@ static int save_image(struct swap_map_handle *handle,
 		ret = snapshot_read_next(snapshot);
 		if (ret <= 0)
 			break;
-		ret = compress_write(handle, data_of(*snapshot), &bio, flags);
+		ret = compress_write(data_of(*snapshot), &bio, flags);
 		if (ret)
 			break;
 		if (!(nr_pages % m))
 			printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	compress_write_finish(handle, &bio, flags);
+	compress_write_finish(&bio, flags);
 	err2 = hib_wait_on_bio_chain(&bio);
 	do_gettimeofday(&stop);
 	if (!ret)
@@ -398,7 +408,6 @@ static int save_image(struct swap_map_handle *handle,
 
 int swsusp_write(unsigned int flags)
 {
-	struct swap_map_handle handle;
 	struct snapshot_handle snapshot;
 	struct swsusp_info *header;
 	unsigned long pages;
@@ -410,7 +419,7 @@ int swsusp_write(unsigned int flags)
 		return error;
 
 	pages = snapshot_get_image_size();
-	error = get_swap_writer(&handle, pages, flags);
+	error = get_swap_writer(pages, flags);
 	if (error) {
 		printk(KERN_ERR "PM: Cannot get swap writer\n");
 		compress_image_cleanup();
@@ -425,12 +434,12 @@ int swsusp_write(unsigned int flags)
 		goto out_finish;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = swap_write_page(&handle, header, NULL);
+	error = swap_write_page(header, NULL);
 	if (!error)
-		error = save_image(&handle, &snapshot, pages - 1, flags);
+		error = save_image(&snapshot, pages - 1, flags);
 out_finish:
 	compress_image_cleanup();
-	error = swap_writer_finish(&handle, flags, error);
+	error = swap_writer_finish(flags, error);
 	return error;
 }
 
@@ -439,15 +448,14 @@ out_finish:
  *	in a file-alike way
  */
 
-static void release_swap_reader(struct swap_map_handle *handle)
+static void release_swap_reader(void)
 {
-	if (handle->cur)
-		free_page((unsigned long)handle->cur);
-	handle->cur = NULL;
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
 }
 
-static int get_swap_reader(struct swap_map_handle *handle,
-		unsigned int *flags_p)
+static int get_swap_reader(unsigned int *flags_p)
 {
 	int error;
 
@@ -456,48 +464,47 @@ static int get_swap_reader(struct swap_map_handle *handle,
 	if (!swsusp_header->image) /* how can this happen? */
 		return -EINVAL;
 
-	handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
-	if (!handle->cur)
+	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
+	if (!handle.cur)
 		return -ENOMEM;
 
-	error = hib_bio_read_page(swsusp_header->image, handle->cur, NULL);
+	error = hib_bio_read_page(swsusp_header->image, handle.cur, NULL);
 	if (error) {
-		release_swap_reader(handle);
+		release_swap_reader();
 		return error;
 	}
-	handle->k = 0;
+	handle.k = 0;
 	return 0;
 }
 
-int swap_read_page(struct swap_map_handle *handle, void *buf,
-				struct bio **bio_chain)
+int swap_read_page(void *buf, struct bio **bio_chain)
 {
 	sector_t offset;
 	int error;
 
-	if (!handle->cur)
+	if (!handle.cur)
 		return -EINVAL;
-	offset = handle->cur->entries[handle->k];
+	offset = handle.cur->entries[handle.k];
 	if (!offset)
 		return -EFAULT;
 	error = hib_bio_read_page(offset, buf, bio_chain);
 	if (error)
 		return error;
-	if (++handle->k >= MAP_PAGE_ENTRIES) {
+	if (++handle.k >= MAP_PAGE_ENTRIES) {
 		error = hib_wait_on_bio_chain(bio_chain);
-		handle->k = 0;
-		offset = handle->cur->next_swap;
+		handle.k = 0;
+		offset = handle.cur->next_swap;
 		if (!offset)
-			release_swap_reader(handle);
+			release_swap_reader();
 		else if (!error)
-			error = hib_bio_read_page(offset, handle->cur, NULL);
+			error = hib_bio_read_page(offset, handle.cur, NULL);
 	}
 	return error;
 }
 
-static int swap_reader_finish(struct swap_map_handle *handle)
+static int swap_reader_finish(void)
 {
-	release_swap_reader(handle);
+	release_swap_reader();
 
 	return 0;
 }
@@ -508,9 +515,8 @@ static int swap_reader_finish(struct swap_map_handle *handle)
  *	(assume there are @nr_pages pages to load)
  */
 
-static int load_image(struct swap_map_handle *handle,
-                      struct snapshot_handle *snapshot,
-                      unsigned int nr_to_read, int flags)
+static int load_image(struct snapshot_handle *snapshot,
+		unsigned int nr_to_read, int flags)
 {
 	unsigned int m;
 	int error = 0;
@@ -533,7 +539,7 @@ static int load_image(struct swap_map_handle *handle,
 		error = snapshot_write_next(snapshot);
 		if (error <= 0)
 			break;
-		error = compress_read(handle, data_of(*snapshot), &bio, flags);
+		error = compress_read(data_of(*snapshot), &bio, flags);
 		if (error)
 			break;
 		if (snapshot->sync_read)
@@ -569,7 +575,6 @@ static int load_image(struct swap_map_handle *handle,
 int swsusp_read(unsigned int *flags_p)
 {
 	int error = 0;
-	struct swap_map_handle handle;
 	struct snapshot_handle snapshot;
 	struct swsusp_info *header;
 
@@ -585,16 +590,14 @@ int swsusp_read(unsigned int *flags_p)
 		return error < 0 ? error : -EFAULT;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = get_swap_reader(&handle, flags_p);
+	error = get_swap_reader(flags_p);
 	if (error)
 		goto end;
 	if (!error)
-		error = swap_read_page(&handle, header, NULL);
-	if (!error) {
-		error = load_image(&handle, &snapshot, header->pages - 1,
-				*flags_p);
-	}
-	swap_reader_finish(&handle);
+		error = swap_read_page(header, NULL);
+	if (!error)
+		error = load_image(&snapshot, header->pages - 1, *flags_p);
+	swap_reader_finish();
 end:
 	compress_image_cleanup();
 	if (!error)
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
index e9ad377..7d109ad 100644
--- a/kernel/power/swap.h
+++ b/kernel/power/swap.h
@@ -10,19 +10,5 @@
  *
  */
 
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	sector_t cur_swap;
-	sector_t first_sector;
-	unsigned int k;
-};
-
-int swap_write_page(struct swap_map_handle *handle, void *buf,
-				struct bio **bio_chain);
-int swap_read_page(struct swap_map_handle *handle, void *buf,
-				struct bio **bio_chain);
+int swap_write_page(void *buf, struct bio **bio_chain);
+int swap_read_page(void *buf, struct bio **bio_chain);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 11/23] Hibernation: Stop passing bio_chain around
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (21 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 11/23] Hibernation: Stop passing bio_chain around Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 12/23] Hibernation: Move block i/o fns to block_io.c Nigel Cunningham
                   ` (30 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Stop using the struct bio **bio_chain as a means of tracking
outstanding i/o and signalling when we want synchronous i/o.
Instead, keep a bio_chain in the block_io code and use a flag
to explicitly request synchronous I/O.

Note that this patch includes a slight modification to the
behaviour of swsusp. Until now, if a page could not be allocated
for the copy of a page to be written, that bio and all future
pages would be written synchronously. After this patch, the
bio with the failed allocation is written synchronously, but we
still write future pages asynchronously if possible.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   27 +++++++++++----------
 kernel/power/compress.c |   22 +++++++++---------
 kernel/power/compress.h |    6 ++--
 kernel/power/power.h    |    8 ++----
 kernel/power/swap.c     |   58 +++++++++++++++++++++-------------------------
 kernel/power/swap.h     |    4 +-
 6 files changed, 60 insertions(+), 65 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 83bbc7c..aa239a2 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -14,6 +14,8 @@
 
 #include "power.h"
 
+static struct bio *bio_chain;
+
 /**
  *	submit - submit BIO request.
  *	@rw:	READ or WRITE.
@@ -26,7 +28,7 @@
  *	Then submit it and, if @bio_chain == NULL, wait.
  */
 static int submit(int rw, struct block_device *bdev, sector_t sector,
-		struct page *page, struct bio **bio_chain)
+		struct page *page, int sync)
 {
 	const int bio_rw = rw | REQ_SYNC | REQ_UNPLUG;
 	struct bio *bio;
@@ -46,7 +48,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	lock_page(page);
 	bio_get(bio);
 
-	if (bio_chain == NULL) {
+	if (sync) {
 		submit_bio(bio_rw, bio);
 		wait_on_page_locked(page);
 		if (rw == READ)
@@ -55,26 +57,26 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	} else {
 		if (rw == READ)
 			get_page(page);	/* These pages are freed later */
-		bio->bi_private = *bio_chain;
-		*bio_chain = bio;
+		bio->bi_private = bio_chain;
+		bio_chain = bio;
 		submit_bio(bio_rw, bio);
 	}
 	return 0;
 }
 
-int hib_bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
+int hib_bio_read_page(pgoff_t page_off, void *addr, int sync)
 {
 	return submit(READ, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
-			virt_to_page(addr), bio_chain);
+			virt_to_page(addr), sync);
 }
 
-int hib_bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
+int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 {
 	return submit(WRITE, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
-			virt_to_page(addr), bio_chain);
+			virt_to_page(addr), sync);
 }
 
-int hib_wait_on_bio_chain(struct bio **bio_chain)
+int hib_wait_on_bio_chain(void)
 {
 	struct bio *bio;
 	struct bio *next_bio;
@@ -83,9 +85,8 @@ int hib_wait_on_bio_chain(struct bio **bio_chain)
 	if (bio_chain == NULL)
 		return 0;
 
-	bio = *bio_chain;
-	if (bio == NULL)
-		return 0;
+	bio = bio_chain;
+
 	while (bio) {
 		struct page *page;
 
@@ -98,6 +99,6 @@ int hib_wait_on_bio_chain(struct bio **bio_chain)
 		bio_put(bio);
 		bio = next_bio;
 	}
-	*bio_chain = NULL;
+	bio_chain = NULL;
 	return ret;
 }
diff --git a/kernel/power/compress.c b/kernel/power/compress.c
index b8b8c63..bb9b9ab 100644
--- a/kernel/power/compress.c
+++ b/kernel/power/compress.c
@@ -78,7 +78,7 @@ int compress_image_init(void)
 	return 0;
 }
 
-static int compress_and_write(struct bio **bio)
+static int compress_and_write(void)
 {
 	int ret;
 
@@ -111,7 +111,7 @@ static int compress_and_write(struct bio **bio)
 	for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
 		memcpy(page, cmp + off, PAGE_SIZE);
 
-		ret = swap_write_page(page, bio);
+		ret = swap_write_page(page, 0);
 		if (ret)
 			return ret;
 	}
@@ -120,30 +120,30 @@ static int compress_and_write(struct bio **bio)
 	return 0;
 }
 
-int compress_write(char *buf, struct bio **bio, int flags)
+int compress_write(char *buf, int flags)
 {
 	int ret = 0;
 
 	if (flags & SF_NOCOMPRESS_MODE)
-		return swap_write_page(buf, bio);
+		return swap_write_page(buf, 0);
 
 	if (off == LZO_UNC_SIZE)
-		ret = compress_and_write(bio);
+		ret = compress_and_write();
 
 	memcpy(unc + off, buf, PAGE_SIZE);
 	off += PAGE_SIZE;
 	return ret;
 }
 
-void compress_write_finish(struct bio **bio, int flags)
+void compress_write_finish(int flags)
 {
 	if (!(flags & SF_NOCOMPRESS_MODE))
-		compress_and_write(bio);
+		compress_and_write();
 }
 
 static int read_and_decompress(void)
 {
-	int error = swap_read_page(page, NULL), off;
+	int error = swap_read_page(page, 1), off;
 	cmp_len = *(size_t *)page;
 
 	if (unlikely(!cmp_len ||
@@ -154,7 +154,7 @@ static int read_and_decompress(void)
 
 	memcpy(cmp, page, PAGE_SIZE);
 	for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-		error = swap_read_page(page, NULL); /* sync */
+		error = swap_read_page(page, 1); /* sync */
 		if (error)
 			return error;
 
@@ -179,12 +179,12 @@ static int read_and_decompress(void)
 	return 0;
 }
 
-int compress_read(char *buf, struct bio **bio, int flags)
+int compress_read(char *buf, int flags)
 {
 	int ret = 0;
 
 	if (flags & SF_NOCOMPRESS_MODE)
-		return swap_read_page(buf, bio);
+		return swap_read_page(buf, 0);
 
 	if (!off) {
 		ret = read_and_decompress();
diff --git a/kernel/power/compress.h b/kernel/power/compress.h
index a25f673..df8ea7c 100644
--- a/kernel/power/compress.h
+++ b/kernel/power/compress.h
@@ -12,7 +12,7 @@
 
 int compress_image_init(void);
 void compress_image_cleanup(void);
-int compress_write(char *page, struct bio **bio, int flags);
-void compress_write_finish(struct bio **bio, int flags);
-int compress_read(char *page, struct bio **bio, int flags);
+int compress_write(char *page, int flags);
+void compress_write_finish(int flags);
+int compress_read(char *page, int flags);
 unsigned int compress_extra_pages(unsigned int base, unsigned int flags);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 22f8607..3c11987 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -154,11 +154,9 @@ extern void swsusp_close(fmode_t);
 /* kernel/power/block_io.c */
 extern struct block_device *hib_resume_bdev;
 
-extern int hib_bio_read_page(pgoff_t page_off, void *addr,
-		struct bio **bio_chain);
-extern int hib_bio_write_page(pgoff_t page_off, void *addr,
-		struct bio **bio_chain);
-extern int hib_wait_on_bio_chain(struct bio **bio_chain);
+extern int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
+extern int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
+extern int hib_wait_on_bio_chain(void);
 
 struct timeval;
 /* kernel/power/swsusp.c */
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 7340314..d828fe9 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -173,7 +173,7 @@ static int mark_swapfiles(unsigned int flags)
 {
 	int error;
 
-	hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL);
+	hib_bio_read_page(swsusp_resume_block, swsusp_header, 1);
 	if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) ||
 	    !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
@@ -182,7 +182,7 @@ static int mark_swapfiles(unsigned int flags)
 		swsusp_header->image = handle.first_sector;
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
-					swsusp_header, NULL);
+					swsusp_header, 1);
 	} else {
 		printk(KERN_ERR "PM: Swap header not found!\n");
 		error = -ENODEV;
@@ -221,29 +221,29 @@ static int swsusp_swap_check(void)
  *	write_page - Write one page to given swap location.
  *	@buf:		Address we're writing.
  *	@offset:	Offset of the swap page we're writing to.
- *	@bio_chain:	Link the next write BIO here
+ *	@sync:		Whether to force synchronous i/o.
  */
 
-static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
+static int write_page(void *buf, sector_t offset, int sync)
 {
 	void *src;
 
 	if (!offset)
 		return -ENOSPC;
 
-	if (bio_chain) {
+	if (!sync) {
 		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
 		if (src) {
 			memcpy(src, buf, PAGE_SIZE);
 		} else {
 			WARN_ON_ONCE(1);
-			bio_chain = NULL;	/* Go synchronous */
+			sync = 1;	/* Go synchronous */
 			src = buf;
 		}
 	} else {
 		src = buf;
 	}
-	return hib_bio_write_page(offset, src, bio_chain);
+	return hib_bio_write_page(offset, src, sync);
 }
 
 static void release_swap_writer(void)
@@ -289,7 +289,7 @@ err_close:
 	return ret;
 }
 
-int swap_write_page(void *buf, struct bio **bio_chain)
+int swap_write_page(void *buf, int sync)
 {
 	int error = 0;
 	sector_t offset;
@@ -297,19 +297,19 @@ int swap_write_page(void *buf, struct bio **bio_chain)
 	if (!handle.cur)
 		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
-	error = write_page(buf, offset, bio_chain);
+	error = write_page(buf, offset, sync);
 	if (error)
 		return error;
 	handle.cur->entries[handle.k++] = offset;
 	if (handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain(bio_chain);
+		error = hib_wait_on_bio_chain();
 		if (error)
 			goto out;
 		offset = hib_extent_next(&sector_extents);
 		if (!offset)
 			return -ENOSPC;
 		handle.cur->next_swap = offset;
-		error = write_page(handle.cur, handle.cur_swap, NULL);
+		error = write_page(handle.cur, handle.cur_swap, 1);
 		if (error)
 			goto out;
 		memset(handle.cur, 0, PAGE_SIZE);
@@ -323,7 +323,7 @@ int swap_write_page(void *buf, struct bio **bio_chain)
 static int flush_swap_writer(void)
 {
 	if (handle.cur && handle.cur_swap)
-		return write_page(handle.cur, handle.cur_swap, NULL);
+		return write_page(handle.cur, handle.cur_swap, 1);
 	else
 		return -EINVAL;
 }
@@ -357,7 +357,6 @@ static int save_image(struct snapshot_handle *snapshot,
 	int ret;
 	int nr_pages;
 	int err2;
-	struct bio *bio;
 	struct timeval start;
 	struct timeval stop;
 	int mps;
@@ -368,21 +367,20 @@ static int save_image(struct snapshot_handle *snapshot,
 	if (!m)
 		m = 1;
 	nr_pages = 0;
-	bio = NULL;
 	do_gettimeofday(&start);
 	while (1) {
 		ret = snapshot_read_next(snapshot);
 		if (ret <= 0)
 			break;
-		ret = compress_write(data_of(*snapshot), &bio, flags);
+		ret = compress_write(data_of(*snapshot), flags);
 		if (ret)
 			break;
 		if (!(nr_pages % m))
 			printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	compress_write_finish(&bio, flags);
-	err2 = hib_wait_on_bio_chain(&bio);
+	compress_write_finish(flags);
+	err2 = hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
 	if (!ret)
 		ret = err2;
@@ -434,7 +432,7 @@ int swsusp_write(unsigned int flags)
 		goto out_finish;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = swap_write_page(header, NULL);
+	error = swap_write_page(header, 1);
 	if (!error)
 		error = save_image(&snapshot, pages - 1, flags);
 out_finish:
@@ -468,7 +466,7 @@ static int get_swap_reader(unsigned int *flags_p)
 	if (!handle.cur)
 		return -ENOMEM;
 
-	error = hib_bio_read_page(swsusp_header->image, handle.cur, NULL);
+	error = hib_bio_read_page(swsusp_header->image, handle.cur, 1);
 	if (error) {
 		release_swap_reader();
 		return error;
@@ -477,7 +475,7 @@ static int get_swap_reader(unsigned int *flags_p)
 	return 0;
 }
 
-int swap_read_page(void *buf, struct bio **bio_chain)
+int swap_read_page(void *buf, int sync)
 {
 	sector_t offset;
 	int error;
@@ -487,17 +485,17 @@ int swap_read_page(void *buf, struct bio **bio_chain)
 	offset = handle.cur->entries[handle.k];
 	if (!offset)
 		return -EFAULT;
-	error = hib_bio_read_page(offset, buf, bio_chain);
+	error = hib_bio_read_page(offset, buf, sync);
 	if (error)
 		return error;
 	if (++handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain(bio_chain);
+		error = hib_wait_on_bio_chain();
 		handle.k = 0;
 		offset = handle.cur->next_swap;
 		if (!offset)
 			release_swap_reader();
 		else if (!error)
-			error = hib_bio_read_page(offset, handle.cur, NULL);
+			error = hib_bio_read_page(offset, handle.cur, 1);
 	}
 	return error;
 }
@@ -522,7 +520,6 @@ static int load_image(struct snapshot_handle *snapshot,
 	int error = 0;
 	struct timeval start;
 	struct timeval stop;
-	struct bio *bio;
 	int err2;
 	unsigned nr_pages;
 	int mps;
@@ -533,24 +530,23 @@ static int load_image(struct snapshot_handle *snapshot,
 	if (!m)
 		m = 1;
 	nr_pages = 0;
-	bio = NULL;
 	do_gettimeofday(&start);
 	for ( ; ; ) {
 		error = snapshot_write_next(snapshot);
 		if (error <= 0)
 			break;
-		error = compress_read(data_of(*snapshot), &bio, flags);
+		error = compress_read(data_of(*snapshot), flags);
 		if (error)
 			break;
 		if (snapshot->sync_read)
-			error = hib_wait_on_bio_chain(&bio);
+			error = hib_wait_on_bio_chain();
 		if (error)
 			break;
 		if (!(nr_pages % m))
 			printk("\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	err2 = hib_wait_on_bio_chain(&bio);
+	err2 = hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
 	if (!error)
 		error = err2;
@@ -594,7 +590,7 @@ int swsusp_read(unsigned int *flags_p)
 	if (error)
 		goto end;
 	if (!error)
-		error = swap_read_page(header, NULL);
+		error = swap_read_page(header, 1);
 	if (!error)
 		error = load_image(&snapshot, header->pages - 1, *flags_p);
 	swap_reader_finish();
@@ -620,7 +616,7 @@ int swsusp_check(void)
 		set_blocksize(hib_resume_bdev, PAGE_SIZE);
 		memset(swsusp_header, 0, PAGE_SIZE);
 		error = hib_bio_read_page(swsusp_resume_block,
-					swsusp_header, NULL);
+					swsusp_header, 1);
 		if (error)
 			goto put;
 
@@ -629,7 +625,7 @@ int swsusp_check(void)
 			memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
 			/* Reset swap signature now */
 			error = hib_bio_write_page(swsusp_resume_block,
-						swsusp_header, NULL);
+						swsusp_header, 1);
 		} else {
 			error = -EINVAL;
 		}
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
index 7d109ad..8e2eed4 100644
--- a/kernel/power/swap.h
+++ b/kernel/power/swap.h
@@ -10,5 +10,5 @@
  *
  */
 
-int swap_write_page(void *buf, struct bio **bio_chain);
-int swap_read_page(void *buf, struct bio **bio_chain);
+int swap_write_page(void *buf, int sync);
+int swap_read_page(void *buf, int sync);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 11/23] Hibernation: Stop passing bio_chain around
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (20 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (31 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Stop using the struct bio **bio_chain as a means of tracking
outstanding i/o and signalling when we want synchronous i/o.
Instead, keep a bio_chain in the block_io code and use a flag
to explicitly request synchronous I/O.

Note that this patch includes a slight modification to the
behaviour of swsusp. Until now, if a page could not be allocated
for the copy of a page to be written, that bio and all future
pages would be written synchronously. After this patch, the
bio with the failed allocation is written synchronously, but we
still write future pages asynchronously if possible.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   27 +++++++++++----------
 kernel/power/compress.c |   22 +++++++++---------
 kernel/power/compress.h |    6 ++--
 kernel/power/power.h    |    8 ++----
 kernel/power/swap.c     |   58 +++++++++++++++++++++-------------------------
 kernel/power/swap.h     |    4 +-
 6 files changed, 60 insertions(+), 65 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 83bbc7c..aa239a2 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -14,6 +14,8 @@
 
 #include "power.h"
 
+static struct bio *bio_chain;
+
 /**
  *	submit - submit BIO request.
  *	@rw:	READ or WRITE.
@@ -26,7 +28,7 @@
  *	Then submit it and, if @bio_chain == NULL, wait.
  */
 static int submit(int rw, struct block_device *bdev, sector_t sector,
-		struct page *page, struct bio **bio_chain)
+		struct page *page, int sync)
 {
 	const int bio_rw = rw | REQ_SYNC | REQ_UNPLUG;
 	struct bio *bio;
@@ -46,7 +48,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	lock_page(page);
 	bio_get(bio);
 
-	if (bio_chain == NULL) {
+	if (sync) {
 		submit_bio(bio_rw, bio);
 		wait_on_page_locked(page);
 		if (rw == READ)
@@ -55,26 +57,26 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	} else {
 		if (rw == READ)
 			get_page(page);	/* These pages are freed later */
-		bio->bi_private = *bio_chain;
-		*bio_chain = bio;
+		bio->bi_private = bio_chain;
+		bio_chain = bio;
 		submit_bio(bio_rw, bio);
 	}
 	return 0;
 }
 
-int hib_bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
+int hib_bio_read_page(pgoff_t page_off, void *addr, int sync)
 {
 	return submit(READ, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
-			virt_to_page(addr), bio_chain);
+			virt_to_page(addr), sync);
 }
 
-int hib_bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
+int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 {
 	return submit(WRITE, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
-			virt_to_page(addr), bio_chain);
+			virt_to_page(addr), sync);
 }
 
-int hib_wait_on_bio_chain(struct bio **bio_chain)
+int hib_wait_on_bio_chain(void)
 {
 	struct bio *bio;
 	struct bio *next_bio;
@@ -83,9 +85,8 @@ int hib_wait_on_bio_chain(struct bio **bio_chain)
 	if (bio_chain == NULL)
 		return 0;
 
-	bio = *bio_chain;
-	if (bio == NULL)
-		return 0;
+	bio = bio_chain;
+
 	while (bio) {
 		struct page *page;
 
@@ -98,6 +99,6 @@ int hib_wait_on_bio_chain(struct bio **bio_chain)
 		bio_put(bio);
 		bio = next_bio;
 	}
-	*bio_chain = NULL;
+	bio_chain = NULL;
 	return ret;
 }
diff --git a/kernel/power/compress.c b/kernel/power/compress.c
index b8b8c63..bb9b9ab 100644
--- a/kernel/power/compress.c
+++ b/kernel/power/compress.c
@@ -78,7 +78,7 @@ int compress_image_init(void)
 	return 0;
 }
 
-static int compress_and_write(struct bio **bio)
+static int compress_and_write(void)
 {
 	int ret;
 
@@ -111,7 +111,7 @@ static int compress_and_write(struct bio **bio)
 	for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
 		memcpy(page, cmp + off, PAGE_SIZE);
 
-		ret = swap_write_page(page, bio);
+		ret = swap_write_page(page, 0);
 		if (ret)
 			return ret;
 	}
@@ -120,30 +120,30 @@ static int compress_and_write(struct bio **bio)
 	return 0;
 }
 
-int compress_write(char *buf, struct bio **bio, int flags)
+int compress_write(char *buf, int flags)
 {
 	int ret = 0;
 
 	if (flags & SF_NOCOMPRESS_MODE)
-		return swap_write_page(buf, bio);
+		return swap_write_page(buf, 0);
 
 	if (off == LZO_UNC_SIZE)
-		ret = compress_and_write(bio);
+		ret = compress_and_write();
 
 	memcpy(unc + off, buf, PAGE_SIZE);
 	off += PAGE_SIZE;
 	return ret;
 }
 
-void compress_write_finish(struct bio **bio, int flags)
+void compress_write_finish(int flags)
 {
 	if (!(flags & SF_NOCOMPRESS_MODE))
-		compress_and_write(bio);
+		compress_and_write();
 }
 
 static int read_and_decompress(void)
 {
-	int error = swap_read_page(page, NULL), off;
+	int error = swap_read_page(page, 1), off;
 	cmp_len = *(size_t *)page;
 
 	if (unlikely(!cmp_len ||
@@ -154,7 +154,7 @@ static int read_and_decompress(void)
 
 	memcpy(cmp, page, PAGE_SIZE);
 	for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-		error = swap_read_page(page, NULL); /* sync */
+		error = swap_read_page(page, 1); /* sync */
 		if (error)
 			return error;
 
@@ -179,12 +179,12 @@ static int read_and_decompress(void)
 	return 0;
 }
 
-int compress_read(char *buf, struct bio **bio, int flags)
+int compress_read(char *buf, int flags)
 {
 	int ret = 0;
 
 	if (flags & SF_NOCOMPRESS_MODE)
-		return swap_read_page(buf, bio);
+		return swap_read_page(buf, 0);
 
 	if (!off) {
 		ret = read_and_decompress();
diff --git a/kernel/power/compress.h b/kernel/power/compress.h
index a25f673..df8ea7c 100644
--- a/kernel/power/compress.h
+++ b/kernel/power/compress.h
@@ -12,7 +12,7 @@
 
 int compress_image_init(void);
 void compress_image_cleanup(void);
-int compress_write(char *page, struct bio **bio, int flags);
-void compress_write_finish(struct bio **bio, int flags);
-int compress_read(char *page, struct bio **bio, int flags);
+int compress_write(char *page, int flags);
+void compress_write_finish(int flags);
+int compress_read(char *page, int flags);
 unsigned int compress_extra_pages(unsigned int base, unsigned int flags);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 22f8607..3c11987 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -154,11 +154,9 @@ extern void swsusp_close(fmode_t);
 /* kernel/power/block_io.c */
 extern struct block_device *hib_resume_bdev;
 
-extern int hib_bio_read_page(pgoff_t page_off, void *addr,
-		struct bio **bio_chain);
-extern int hib_bio_write_page(pgoff_t page_off, void *addr,
-		struct bio **bio_chain);
-extern int hib_wait_on_bio_chain(struct bio **bio_chain);
+extern int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
+extern int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
+extern int hib_wait_on_bio_chain(void);
 
 struct timeval;
 /* kernel/power/swsusp.c */
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 7340314..d828fe9 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -173,7 +173,7 @@ static int mark_swapfiles(unsigned int flags)
 {
 	int error;
 
-	hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL);
+	hib_bio_read_page(swsusp_resume_block, swsusp_header, 1);
 	if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) ||
 	    !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
@@ -182,7 +182,7 @@ static int mark_swapfiles(unsigned int flags)
 		swsusp_header->image = handle.first_sector;
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
-					swsusp_header, NULL);
+					swsusp_header, 1);
 	} else {
 		printk(KERN_ERR "PM: Swap header not found!\n");
 		error = -ENODEV;
@@ -221,29 +221,29 @@ static int swsusp_swap_check(void)
  *	write_page - Write one page to given swap location.
  *	@buf:		Address we're writing.
  *	@offset:	Offset of the swap page we're writing to.
- *	@bio_chain:	Link the next write BIO here
+ *	@sync:		Whether to force synchronous i/o.
  */
 
-static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
+static int write_page(void *buf, sector_t offset, int sync)
 {
 	void *src;
 
 	if (!offset)
 		return -ENOSPC;
 
-	if (bio_chain) {
+	if (!sync) {
 		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
 		if (src) {
 			memcpy(src, buf, PAGE_SIZE);
 		} else {
 			WARN_ON_ONCE(1);
-			bio_chain = NULL;	/* Go synchronous */
+			sync = 1;	/* Go synchronous */
 			src = buf;
 		}
 	} else {
 		src = buf;
 	}
-	return hib_bio_write_page(offset, src, bio_chain);
+	return hib_bio_write_page(offset, src, sync);
 }
 
 static void release_swap_writer(void)
@@ -289,7 +289,7 @@ err_close:
 	return ret;
 }
 
-int swap_write_page(void *buf, struct bio **bio_chain)
+int swap_write_page(void *buf, int sync)
 {
 	int error = 0;
 	sector_t offset;
@@ -297,19 +297,19 @@ int swap_write_page(void *buf, struct bio **bio_chain)
 	if (!handle.cur)
 		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
-	error = write_page(buf, offset, bio_chain);
+	error = write_page(buf, offset, sync);
 	if (error)
 		return error;
 	handle.cur->entries[handle.k++] = offset;
 	if (handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain(bio_chain);
+		error = hib_wait_on_bio_chain();
 		if (error)
 			goto out;
 		offset = hib_extent_next(&sector_extents);
 		if (!offset)
 			return -ENOSPC;
 		handle.cur->next_swap = offset;
-		error = write_page(handle.cur, handle.cur_swap, NULL);
+		error = write_page(handle.cur, handle.cur_swap, 1);
 		if (error)
 			goto out;
 		memset(handle.cur, 0, PAGE_SIZE);
@@ -323,7 +323,7 @@ int swap_write_page(void *buf, struct bio **bio_chain)
 static int flush_swap_writer(void)
 {
 	if (handle.cur && handle.cur_swap)
-		return write_page(handle.cur, handle.cur_swap, NULL);
+		return write_page(handle.cur, handle.cur_swap, 1);
 	else
 		return -EINVAL;
 }
@@ -357,7 +357,6 @@ static int save_image(struct snapshot_handle *snapshot,
 	int ret;
 	int nr_pages;
 	int err2;
-	struct bio *bio;
 	struct timeval start;
 	struct timeval stop;
 	int mps;
@@ -368,21 +367,20 @@ static int save_image(struct snapshot_handle *snapshot,
 	if (!m)
 		m = 1;
 	nr_pages = 0;
-	bio = NULL;
 	do_gettimeofday(&start);
 	while (1) {
 		ret = snapshot_read_next(snapshot);
 		if (ret <= 0)
 			break;
-		ret = compress_write(data_of(*snapshot), &bio, flags);
+		ret = compress_write(data_of(*snapshot), flags);
 		if (ret)
 			break;
 		if (!(nr_pages % m))
 			printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	compress_write_finish(&bio, flags);
-	err2 = hib_wait_on_bio_chain(&bio);
+	compress_write_finish(flags);
+	err2 = hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
 	if (!ret)
 		ret = err2;
@@ -434,7 +432,7 @@ int swsusp_write(unsigned int flags)
 		goto out_finish;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = swap_write_page(header, NULL);
+	error = swap_write_page(header, 1);
 	if (!error)
 		error = save_image(&snapshot, pages - 1, flags);
 out_finish:
@@ -468,7 +466,7 @@ static int get_swap_reader(unsigned int *flags_p)
 	if (!handle.cur)
 		return -ENOMEM;
 
-	error = hib_bio_read_page(swsusp_header->image, handle.cur, NULL);
+	error = hib_bio_read_page(swsusp_header->image, handle.cur, 1);
 	if (error) {
 		release_swap_reader();
 		return error;
@@ -477,7 +475,7 @@ static int get_swap_reader(unsigned int *flags_p)
 	return 0;
 }
 
-int swap_read_page(void *buf, struct bio **bio_chain)
+int swap_read_page(void *buf, int sync)
 {
 	sector_t offset;
 	int error;
@@ -487,17 +485,17 @@ int swap_read_page(void *buf, struct bio **bio_chain)
 	offset = handle.cur->entries[handle.k];
 	if (!offset)
 		return -EFAULT;
-	error = hib_bio_read_page(offset, buf, bio_chain);
+	error = hib_bio_read_page(offset, buf, sync);
 	if (error)
 		return error;
 	if (++handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain(bio_chain);
+		error = hib_wait_on_bio_chain();
 		handle.k = 0;
 		offset = handle.cur->next_swap;
 		if (!offset)
 			release_swap_reader();
 		else if (!error)
-			error = hib_bio_read_page(offset, handle.cur, NULL);
+			error = hib_bio_read_page(offset, handle.cur, 1);
 	}
 	return error;
 }
@@ -522,7 +520,6 @@ static int load_image(struct snapshot_handle *snapshot,
 	int error = 0;
 	struct timeval start;
 	struct timeval stop;
-	struct bio *bio;
 	int err2;
 	unsigned nr_pages;
 	int mps;
@@ -533,24 +530,23 @@ static int load_image(struct snapshot_handle *snapshot,
 	if (!m)
 		m = 1;
 	nr_pages = 0;
-	bio = NULL;
 	do_gettimeofday(&start);
 	for ( ; ; ) {
 		error = snapshot_write_next(snapshot);
 		if (error <= 0)
 			break;
-		error = compress_read(data_of(*snapshot), &bio, flags);
+		error = compress_read(data_of(*snapshot), flags);
 		if (error)
 			break;
 		if (snapshot->sync_read)
-			error = hib_wait_on_bio_chain(&bio);
+			error = hib_wait_on_bio_chain();
 		if (error)
 			break;
 		if (!(nr_pages % m))
 			printk("\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	err2 = hib_wait_on_bio_chain(&bio);
+	err2 = hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
 	if (!error)
 		error = err2;
@@ -594,7 +590,7 @@ int swsusp_read(unsigned int *flags_p)
 	if (error)
 		goto end;
 	if (!error)
-		error = swap_read_page(header, NULL);
+		error = swap_read_page(header, 1);
 	if (!error)
 		error = load_image(&snapshot, header->pages - 1, *flags_p);
 	swap_reader_finish();
@@ -620,7 +616,7 @@ int swsusp_check(void)
 		set_blocksize(hib_resume_bdev, PAGE_SIZE);
 		memset(swsusp_header, 0, PAGE_SIZE);
 		error = hib_bio_read_page(swsusp_resume_block,
-					swsusp_header, NULL);
+					swsusp_header, 1);
 		if (error)
 			goto put;
 
@@ -629,7 +625,7 @@ int swsusp_check(void)
 			memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
 			/* Reset swap signature now */
 			error = hib_bio_write_page(swsusp_resume_block,
-						swsusp_header, NULL);
+						swsusp_header, 1);
 		} else {
 			error = -EINVAL;
 		}
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
index 7d109ad..8e2eed4 100644
--- a/kernel/power/swap.h
+++ b/kernel/power/swap.h
@@ -10,5 +10,5 @@
  *
  */
 
-int swap_write_page(void *buf, struct bio **bio_chain);
-int swap_read_page(void *buf, struct bio **bio_chain);
+int swap_write_page(void *buf, int sync);
+int swap_read_page(void *buf, int sync);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 12/23] Hibernation: Move block i/o fns to block_io.c
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (23 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 12/23] Hibernation: Move block i/o fns to block_io.c Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (28 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Move the functions that specifically deal with submitting I/O
to block_io.c. This helps us in working towards having a clean
separation between swap specific functions (which will be all
that will be in swap.c eventually) and low level block i/o
functions (block_io.c) that are/will be agnostic with regard to
the source of the storage. The block_io.c functions will thus
also be useable when support for storing an image in a generic
file (non swap) is added later.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |  199 ++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/block_io.h |   23 ++++++
 kernel/power/compress.c |    2 +-
 kernel/power/swap.c     |  203 +++--------------------------------------------
 kernel/power/swap.h     |   14 ---
 5 files changed, 236 insertions(+), 205 deletions(-)
 create mode 100644 kernel/power/block_io.h
 delete mode 100644 kernel/power/swap.h

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index aa239a2..5edcb08 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -13,6 +13,7 @@
 #include <linux/swap.h>
 
 #include "power.h"
+#include "extents.h"
 
 static struct bio *bio_chain;
 
@@ -102,3 +103,201 @@ int hib_wait_on_bio_chain(void)
 	bio_chain = NULL;
 	return ret;
 }
+
+/*
+ *	The swap map is a data structure used for keeping track of each page
+ *	written to a swap partition.  It consists of many swap_map_page
+ *	structures that contain each an array of MAP_PAGE_SIZE swap entries.
+ *	These structures are stored on the swap and linked together with the
+ *	help of the .next_swap member.
+ *
+ *	The swap map is created during suspend.  The swap map pages are
+ *	allocated and populated one at a time, so we only need one memory
+ *	page to set up the entire structure.
+ *
+ *	During resume we also only need to use one swap_map_page structure
+ *	at a time.
+ */
+
+#define MAP_PAGE_ENTRIES	(PAGE_SIZE / sizeof(sector_t) - 1)
+
+struct swap_map_page {
+	sector_t entries[MAP_PAGE_ENTRIES];
+	sector_t next_swap;
+};
+
+/**
+ *	The swap_map_handle structure is used for handling swap in
+ *	a file-alike way
+ */
+
+struct swap_map_handle {
+	struct swap_map_page *cur;
+	sector_t cur_swap;
+	sector_t first_sector;
+	unsigned int k;
+};
+
+static struct swap_map_handle handle;
+
+extern struct hib_extent_state sector_extents;
+
+/* Calculate the overhead needed for storing n pages */
+unsigned int hib_bio_overhead(unsigned int nr_pages)
+{
+	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+}
+
+/* Get the first sector of the image proper, for storing in the signature */
+sector_t hib_get_first_sector(void)
+{
+	return handle.first_sector;
+}
+
+/**
+ *	write_page - Write one page to given swap location.
+ *	@buf:		Address we're writing.
+ *	@offset:	Offset of the swap page we're writing to.
+ *	@sync:		Whether to force synchronous i/o.
+ */
+
+static int write_page(void *buf, sector_t offset, int sync)
+{
+	void *src;
+
+	if (!offset)
+		return -ENOSPC;
+
+	if (!sync) {
+		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+		if (src) {
+			memcpy(src, buf, PAGE_SIZE);
+		} else {
+			WARN_ON_ONCE(1);
+			sync = 1;	/* Go synchronous */
+			src = buf;
+		}
+	} else {
+		src = buf;
+	}
+	return hib_bio_write_page(offset, src, sync);
+}
+
+void release_swap_writer(void)
+{
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
+}
+
+int hib_bio_prepare_write(void)
+{
+	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
+
+	if (!handle.cur)
+		return -ENOMEM;
+
+	handle.cur_swap = hib_extent_next(&sector_extents);
+
+	if (!handle.cur_swap) {
+		release_swap_writer();
+		return -ENOSPC;
+	}
+
+	handle.k = 0;
+	handle.first_sector = handle.cur_swap;
+	return 0;
+}
+
+int swap_write_page(void *buf, int sync)
+{
+	int error = 0;
+	sector_t offset;
+
+	if (!handle.cur)
+		return -EINVAL;
+	offset = hib_extent_next(&sector_extents);
+	error = write_page(buf, offset, sync);
+	if (error)
+		return error;
+	handle.cur->entries[handle.k++] = offset;
+	if (handle.k >= MAP_PAGE_ENTRIES) {
+		error = hib_wait_on_bio_chain();
+		if (error)
+			goto out;
+		offset = hib_extent_next(&sector_extents);
+		if (!offset)
+			return -ENOSPC;
+		handle.cur->next_swap = offset;
+		error = write_page(handle.cur, handle.cur_swap, 1);
+		if (error)
+			goto out;
+		memset(handle.cur, 0, PAGE_SIZE);
+		handle.cur_swap = offset;
+		handle.k = 0;
+	}
+ out:
+	return error;
+}
+
+int flush_swap_writer(void)
+{
+	if (handle.cur && handle.cur_swap)
+		return write_page(handle.cur, handle.cur_swap, 1);
+	else
+		return -EINVAL;
+}
+
+/**
+ *	The following functions allow us to read data using a swap map
+ *	in a file-alike way
+ */
+
+void release_swap_reader(void)
+{
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
+}
+
+int get_swap_reader(unsigned int *flags_p, sector_t first_page)
+{
+	int error;
+
+	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
+	if (!handle.cur)
+		return -ENOMEM;
+
+	error = hib_bio_read_page(first_page, handle.cur, 1);
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+	handle.k = 0;
+	return 0;
+}
+
+int swap_read_page(void *buf, int sync)
+{
+	sector_t offset;
+	int error;
+
+	if (!handle.cur)
+		return -EINVAL;
+	offset = handle.cur->entries[handle.k];
+	if (!offset)
+		return -EFAULT;
+	error = hib_bio_read_page(offset, buf, sync);
+	if (error)
+		return error;
+	if (++handle.k >= MAP_PAGE_ENTRIES) {
+		error = hib_wait_on_bio_chain();
+		handle.k = 0;
+		offset = handle.cur->next_swap;
+		if (!offset)
+			release_swap_reader();
+		else if (!error)
+			error = hib_bio_read_page(offset, handle.cur, 1);
+	}
+	return error;
+}
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
new file mode 100644
index 0000000..2f91d6d
--- /dev/null
+++ b/kernel/power/block_io.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
+ * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ */
+
+/* Low level routines */
+int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
+int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
+int hib_wait_on_bio_chain(void);
+
+unsigned int hib_bio_overhead(unsigned int nr_pages);
+sector_t hib_get_first_sector(void);
+extern struct hib_extent_state sector_extents;
+void release_swap_writer(void);
+int hib_bio_prepare_write(void);
+int flush_swap_writer(void);
+int swap_write_page(void *buf, int sync);
+int get_swap_reader(unsigned int *flags_p, sector_t first_page);
+void release_swap_reader(void);
+int swap_read_page(void *buf, int sync);
diff --git a/kernel/power/compress.c b/kernel/power/compress.c
index bb9b9ab..773f8d8 100644
--- a/kernel/power/compress.c
+++ b/kernel/power/compress.c
@@ -15,7 +15,7 @@
 #include <linux/vmalloc.h>
 
 #include "power.h"
-#include "swap.h"
+#include "block_io.h"
 
 /* We need to remember how much compressed data we need to read. */
 #define LZO_HEADER	sizeof(size_t)
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index d828fe9..178fd31 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -17,47 +17,11 @@
 
 #include "power.h"
 #include "compress.h"
-#include "swap.h"
 #include "extents.h"
+#include "block_io.h"
 
 #define SWSUSP_SIG	"S1SUSPEND"
 
-/*
- *	The swap map is a data structure used for keeping track of each page
- *	written to a swap partition.  It consists of many swap_map_page
- *	structures that contain each an array of MAP_PAGE_ENTRIES swap entries.
- *	These structures are stored on the swap and linked together with the
- *	help of the .next_swap member.
- *
- *	The swap map is created during suspend.  The swap map pages are
- *	allocated and populated one at a time, so we only need one memory
- *	page to set up the entire structure.
- *
- *	During resume we also only need to use one swap_map_page structure
- *	at a time.
- */
-
-#define MAP_PAGE_ENTRIES	(PAGE_SIZE / sizeof(sector_t) - 1)
-
-struct swap_map_page {
-	sector_t entries[MAP_PAGE_ENTRIES];
-	sector_t next_swap;
-};
-
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	sector_t cur_swap;
-	sector_t first_sector;
-	unsigned int k;
-};
-
-static struct swap_map_handle handle;
-
 static unsigned short root_swap = 0xffff;
 
 struct swsusp_header {
@@ -72,7 +36,7 @@ struct swsusp_header {
 static struct swsusp_header *swsusp_header;
 
 static struct hib_extent_state swap_extents;
-static struct hib_extent_state sector_extents;
+struct hib_extent_state sector_extents;
 
 /**
  *	alloc_swapdev_block - allocate a swap page and register that it has
@@ -121,7 +85,7 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 	unsigned int free_swap = count_swap_pages(root_swap, 1);
 
 	nr_pages += compress_extra_pages(nr_pages, flags);
-	nr_pages += DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+	nr_pages += hib_bio_overhead(nr_pages);
 
 	pr_debug("PM: Free swap pages: %u\n", free_swap);
 	if (free_swap < nr_pages)
@@ -179,7 +143,7 @@ static int mark_swapfiles(unsigned int flags)
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
 		memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
 		swsusp_header->write_speed = write_speed;
-		swsusp_header->image = handle.first_sector;
+		swsusp_header->image = hib_get_first_sector();
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
 					swsusp_header, 1);
@@ -217,42 +181,6 @@ static int swsusp_swap_check(void)
 	return res;
 }
 
-/**
- *	write_page - Write one page to given swap location.
- *	@buf:		Address we're writing.
- *	@offset:	Offset of the swap page we're writing to.
- *	@sync:		Whether to force synchronous i/o.
- */
-
-static int write_page(void *buf, sector_t offset, int sync)
-{
-	void *src;
-
-	if (!offset)
-		return -ENOSPC;
-
-	if (!sync) {
-		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-		if (src) {
-			memcpy(src, buf, PAGE_SIZE);
-		} else {
-			WARN_ON_ONCE(1);
-			sync = 1;	/* Go synchronous */
-			src = buf;
-		}
-	} else {
-		src = buf;
-	}
-	return hib_bio_write_page(offset, src, sync);
-}
-
-static void release_swap_writer(void)
-{
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
-}
-
 static int get_swap_writer(unsigned long pages, unsigned int flags)
 {
 	int ret;
@@ -264,70 +192,19 @@ static int get_swap_writer(unsigned long pages, unsigned int flags)
 					"swapon -a.\n");
 		return ret;
 	}
-	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
-	if (!handle.cur) {
-		ret = -ENOMEM;
-		goto err_close;
-	}
 	if (!allocate_swap(pages, flags)) {
 		printk(KERN_ERR "PM: Not enough free swap\n");
 		ret = -ENOSPC;
 		goto err_close;
 	}
-	handle.cur_swap = hib_extent_next(&sector_extents);
-	if (!handle.cur_swap) {
-		ret = -ENOSPC;
-		goto err_rel;
-	}
-	handle.k = 0;
-	handle.first_sector = handle.cur_swap;
-	return 0;
-err_rel:
-	release_swap_writer();
+	ret = hib_bio_prepare_write();
+	if (!ret)
+		return 0;
 err_close:
 	swsusp_close(FMODE_WRITE);
 	return ret;
 }
 
-int swap_write_page(void *buf, int sync)
-{
-	int error = 0;
-	sector_t offset;
-
-	if (!handle.cur)
-		return -EINVAL;
-	offset = hib_extent_next(&sector_extents);
-	error = write_page(buf, offset, sync);
-	if (error)
-		return error;
-	handle.cur->entries[handle.k++] = offset;
-	if (handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		if (error)
-			goto out;
-		offset = hib_extent_next(&sector_extents);
-		if (!offset)
-			return -ENOSPC;
-		handle.cur->next_swap = offset;
-		error = write_page(handle.cur, handle.cur_swap, 1);
-		if (error)
-			goto out;
-		memset(handle.cur, 0, PAGE_SIZE);
-		handle.cur_swap = offset;
-		handle.k = 0;
-	}
- out:
-	return error;
-}
-
-static int flush_swap_writer(void)
-{
-	if (handle.cur && handle.cur_swap)
-		return write_page(handle.cur, handle.cur_swap, 1);
-	else
-		return -EINVAL;
-}
-
 static int swap_writer_finish(unsigned int flags, int error)
 {
 	if (!error) {
@@ -441,65 +318,6 @@ out_finish:
 	return error;
 }
 
-/**
- *	The following functions allow us to read data using a swap map
- *	in a file-alike way
- */
-
-static void release_swap_reader(void)
-{
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
-}
-
-static int get_swap_reader(unsigned int *flags_p)
-{
-	int error;
-
-	*flags_p = swsusp_header->flags;
-
-	if (!swsusp_header->image) /* how can this happen? */
-		return -EINVAL;
-
-	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
-	if (!handle.cur)
-		return -ENOMEM;
-
-	error = hib_bio_read_page(swsusp_header->image, handle.cur, 1);
-	if (error) {
-		release_swap_reader();
-		return error;
-	}
-	handle.k = 0;
-	return 0;
-}
-
-int swap_read_page(void *buf, int sync)
-{
-	sector_t offset;
-	int error;
-
-	if (!handle.cur)
-		return -EINVAL;
-	offset = handle.cur->entries[handle.k];
-	if (!offset)
-		return -EFAULT;
-	error = hib_bio_read_page(offset, buf, sync);
-	if (error)
-		return error;
-	if (++handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		handle.k = 0;
-		offset = handle.cur->next_swap;
-		if (!offset)
-			release_swap_reader();
-		else if (!error)
-			error = hib_bio_read_page(offset, handle.cur, 1);
-	}
-	return error;
-}
-
 static int swap_reader_finish(void)
 {
 	release_swap_reader();
@@ -586,7 +404,12 @@ int swsusp_read(unsigned int *flags_p)
 		return error < 0 ? error : -EFAULT;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = get_swap_reader(flags_p);
+	*flags_p = swsusp_header->flags;
+	if (!swsusp_header->image) { /* how can this happen? */
+		error = -EINVAL;
+		goto end;
+	}
+	error = get_swap_reader(flags_p, swsusp_header->image);
 	if (error)
 		goto end;
 	if (!error)
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
deleted file mode 100644
index 8e2eed4..0000000
--- a/kernel/power/swap.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * linux/kernel/power/swap.h
- *
- * This file provides declarations for functions and structures from
- * kernel/power/swap.c.
- *
- * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
- *
- * This file is released under the GPLv2.
- *
- */
-
-int swap_write_page(void *buf, int sync);
-int swap_read_page(void *buf, int sync);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 12/23] Hibernation: Move block i/o fns to block_io.c
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (24 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 13/23] Hibernation: Partial page I/O support Nigel Cunningham
                   ` (27 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Move the functions that specifically deal with submitting I/O
to block_io.c. This helps us in working towards having a clean
separation between swap specific functions (which will be all
that will be in swap.c eventually) and low level block i/o
functions (block_io.c) that are/will be agnostic with regard to
the source of the storage. The block_io.c functions will thus
also be useable when support for storing an image in a generic
file (non swap) is added later.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |  199 ++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/block_io.h |   23 ++++++
 kernel/power/compress.c |    2 +-
 kernel/power/swap.c     |  203 +++--------------------------------------------
 kernel/power/swap.h     |   14 ---
 5 files changed, 236 insertions(+), 205 deletions(-)
 create mode 100644 kernel/power/block_io.h
 delete mode 100644 kernel/power/swap.h

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index aa239a2..5edcb08 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -13,6 +13,7 @@
 #include <linux/swap.h>
 
 #include "power.h"
+#include "extents.h"
 
 static struct bio *bio_chain;
 
@@ -102,3 +103,201 @@ int hib_wait_on_bio_chain(void)
 	bio_chain = NULL;
 	return ret;
 }
+
+/*
+ *	The swap map is a data structure used for keeping track of each page
+ *	written to a swap partition.  It consists of many swap_map_page
+ *	structures that contain each an array of MAP_PAGE_SIZE swap entries.
+ *	These structures are stored on the swap and linked together with the
+ *	help of the .next_swap member.
+ *
+ *	The swap map is created during suspend.  The swap map pages are
+ *	allocated and populated one at a time, so we only need one memory
+ *	page to set up the entire structure.
+ *
+ *	During resume we also only need to use one swap_map_page structure
+ *	at a time.
+ */
+
+#define MAP_PAGE_ENTRIES	(PAGE_SIZE / sizeof(sector_t) - 1)
+
+struct swap_map_page {
+	sector_t entries[MAP_PAGE_ENTRIES];
+	sector_t next_swap;
+};
+
+/**
+ *	The swap_map_handle structure is used for handling swap in
+ *	a file-alike way
+ */
+
+struct swap_map_handle {
+	struct swap_map_page *cur;
+	sector_t cur_swap;
+	sector_t first_sector;
+	unsigned int k;
+};
+
+static struct swap_map_handle handle;
+
+extern struct hib_extent_state sector_extents;
+
+/* Calculate the overhead needed for storing n pages */
+unsigned int hib_bio_overhead(unsigned int nr_pages)
+{
+	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+}
+
+/* Get the first sector of the image proper, for storing in the signature */
+sector_t hib_get_first_sector(void)
+{
+	return handle.first_sector;
+}
+
+/**
+ *	write_page - Write one page to given swap location.
+ *	@buf:		Address we're writing.
+ *	@offset:	Offset of the swap page we're writing to.
+ *	@sync:		Whether to force synchronous i/o.
+ */
+
+static int write_page(void *buf, sector_t offset, int sync)
+{
+	void *src;
+
+	if (!offset)
+		return -ENOSPC;
+
+	if (!sync) {
+		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+		if (src) {
+			memcpy(src, buf, PAGE_SIZE);
+		} else {
+			WARN_ON_ONCE(1);
+			sync = 1;	/* Go synchronous */
+			src = buf;
+		}
+	} else {
+		src = buf;
+	}
+	return hib_bio_write_page(offset, src, sync);
+}
+
+void release_swap_writer(void)
+{
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
+}
+
+int hib_bio_prepare_write(void)
+{
+	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
+
+	if (!handle.cur)
+		return -ENOMEM;
+
+	handle.cur_swap = hib_extent_next(&sector_extents);
+
+	if (!handle.cur_swap) {
+		release_swap_writer();
+		return -ENOSPC;
+	}
+
+	handle.k = 0;
+	handle.first_sector = handle.cur_swap;
+	return 0;
+}
+
+int swap_write_page(void *buf, int sync)
+{
+	int error = 0;
+	sector_t offset;
+
+	if (!handle.cur)
+		return -EINVAL;
+	offset = hib_extent_next(&sector_extents);
+	error = write_page(buf, offset, sync);
+	if (error)
+		return error;
+	handle.cur->entries[handle.k++] = offset;
+	if (handle.k >= MAP_PAGE_ENTRIES) {
+		error = hib_wait_on_bio_chain();
+		if (error)
+			goto out;
+		offset = hib_extent_next(&sector_extents);
+		if (!offset)
+			return -ENOSPC;
+		handle.cur->next_swap = offset;
+		error = write_page(handle.cur, handle.cur_swap, 1);
+		if (error)
+			goto out;
+		memset(handle.cur, 0, PAGE_SIZE);
+		handle.cur_swap = offset;
+		handle.k = 0;
+	}
+ out:
+	return error;
+}
+
+int flush_swap_writer(void)
+{
+	if (handle.cur && handle.cur_swap)
+		return write_page(handle.cur, handle.cur_swap, 1);
+	else
+		return -EINVAL;
+}
+
+/**
+ *	The following functions allow us to read data using a swap map
+ *	in a file-alike way
+ */
+
+void release_swap_reader(void)
+{
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
+}
+
+int get_swap_reader(unsigned int *flags_p, sector_t first_page)
+{
+	int error;
+
+	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
+	if (!handle.cur)
+		return -ENOMEM;
+
+	error = hib_bio_read_page(first_page, handle.cur, 1);
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+	handle.k = 0;
+	return 0;
+}
+
+int swap_read_page(void *buf, int sync)
+{
+	sector_t offset;
+	int error;
+
+	if (!handle.cur)
+		return -EINVAL;
+	offset = handle.cur->entries[handle.k];
+	if (!offset)
+		return -EFAULT;
+	error = hib_bio_read_page(offset, buf, sync);
+	if (error)
+		return error;
+	if (++handle.k >= MAP_PAGE_ENTRIES) {
+		error = hib_wait_on_bio_chain();
+		handle.k = 0;
+		offset = handle.cur->next_swap;
+		if (!offset)
+			release_swap_reader();
+		else if (!error)
+			error = hib_bio_read_page(offset, handle.cur, 1);
+	}
+	return error;
+}
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
new file mode 100644
index 0000000..2f91d6d
--- /dev/null
+++ b/kernel/power/block_io.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
+ * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ */
+
+/* Low level routines */
+int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
+int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
+int hib_wait_on_bio_chain(void);
+
+unsigned int hib_bio_overhead(unsigned int nr_pages);
+sector_t hib_get_first_sector(void);
+extern struct hib_extent_state sector_extents;
+void release_swap_writer(void);
+int hib_bio_prepare_write(void);
+int flush_swap_writer(void);
+int swap_write_page(void *buf, int sync);
+int get_swap_reader(unsigned int *flags_p, sector_t first_page);
+void release_swap_reader(void);
+int swap_read_page(void *buf, int sync);
diff --git a/kernel/power/compress.c b/kernel/power/compress.c
index bb9b9ab..773f8d8 100644
--- a/kernel/power/compress.c
+++ b/kernel/power/compress.c
@@ -15,7 +15,7 @@
 #include <linux/vmalloc.h>
 
 #include "power.h"
-#include "swap.h"
+#include "block_io.h"
 
 /* We need to remember how much compressed data we need to read. */
 #define LZO_HEADER	sizeof(size_t)
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index d828fe9..178fd31 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -17,47 +17,11 @@
 
 #include "power.h"
 #include "compress.h"
-#include "swap.h"
 #include "extents.h"
+#include "block_io.h"
 
 #define SWSUSP_SIG	"S1SUSPEND"
 
-/*
- *	The swap map is a data structure used for keeping track of each page
- *	written to a swap partition.  It consists of many swap_map_page
- *	structures that contain each an array of MAP_PAGE_ENTRIES swap entries.
- *	These structures are stored on the swap and linked together with the
- *	help of the .next_swap member.
- *
- *	The swap map is created during suspend.  The swap map pages are
- *	allocated and populated one at a time, so we only need one memory
- *	page to set up the entire structure.
- *
- *	During resume we also only need to use one swap_map_page structure
- *	at a time.
- */
-
-#define MAP_PAGE_ENTRIES	(PAGE_SIZE / sizeof(sector_t) - 1)
-
-struct swap_map_page {
-	sector_t entries[MAP_PAGE_ENTRIES];
-	sector_t next_swap;
-};
-
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	sector_t cur_swap;
-	sector_t first_sector;
-	unsigned int k;
-};
-
-static struct swap_map_handle handle;
-
 static unsigned short root_swap = 0xffff;
 
 struct swsusp_header {
@@ -72,7 +36,7 @@ struct swsusp_header {
 static struct swsusp_header *swsusp_header;
 
 static struct hib_extent_state swap_extents;
-static struct hib_extent_state sector_extents;
+struct hib_extent_state sector_extents;
 
 /**
  *	alloc_swapdev_block - allocate a swap page and register that it has
@@ -121,7 +85,7 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 	unsigned int free_swap = count_swap_pages(root_swap, 1);
 
 	nr_pages += compress_extra_pages(nr_pages, flags);
-	nr_pages += DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+	nr_pages += hib_bio_overhead(nr_pages);
 
 	pr_debug("PM: Free swap pages: %u\n", free_swap);
 	if (free_swap < nr_pages)
@@ -179,7 +143,7 @@ static int mark_swapfiles(unsigned int flags)
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
 		memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
 		swsusp_header->write_speed = write_speed;
-		swsusp_header->image = handle.first_sector;
+		swsusp_header->image = hib_get_first_sector();
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
 					swsusp_header, 1);
@@ -217,42 +181,6 @@ static int swsusp_swap_check(void)
 	return res;
 }
 
-/**
- *	write_page - Write one page to given swap location.
- *	@buf:		Address we're writing.
- *	@offset:	Offset of the swap page we're writing to.
- *	@sync:		Whether to force synchronous i/o.
- */
-
-static int write_page(void *buf, sector_t offset, int sync)
-{
-	void *src;
-
-	if (!offset)
-		return -ENOSPC;
-
-	if (!sync) {
-		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-		if (src) {
-			memcpy(src, buf, PAGE_SIZE);
-		} else {
-			WARN_ON_ONCE(1);
-			sync = 1;	/* Go synchronous */
-			src = buf;
-		}
-	} else {
-		src = buf;
-	}
-	return hib_bio_write_page(offset, src, sync);
-}
-
-static void release_swap_writer(void)
-{
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
-}
-
 static int get_swap_writer(unsigned long pages, unsigned int flags)
 {
 	int ret;
@@ -264,70 +192,19 @@ static int get_swap_writer(unsigned long pages, unsigned int flags)
 					"swapon -a.\n");
 		return ret;
 	}
-	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
-	if (!handle.cur) {
-		ret = -ENOMEM;
-		goto err_close;
-	}
 	if (!allocate_swap(pages, flags)) {
 		printk(KERN_ERR "PM: Not enough free swap\n");
 		ret = -ENOSPC;
 		goto err_close;
 	}
-	handle.cur_swap = hib_extent_next(&sector_extents);
-	if (!handle.cur_swap) {
-		ret = -ENOSPC;
-		goto err_rel;
-	}
-	handle.k = 0;
-	handle.first_sector = handle.cur_swap;
-	return 0;
-err_rel:
-	release_swap_writer();
+	ret = hib_bio_prepare_write();
+	if (!ret)
+		return 0;
 err_close:
 	swsusp_close(FMODE_WRITE);
 	return ret;
 }
 
-int swap_write_page(void *buf, int sync)
-{
-	int error = 0;
-	sector_t offset;
-
-	if (!handle.cur)
-		return -EINVAL;
-	offset = hib_extent_next(&sector_extents);
-	error = write_page(buf, offset, sync);
-	if (error)
-		return error;
-	handle.cur->entries[handle.k++] = offset;
-	if (handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		if (error)
-			goto out;
-		offset = hib_extent_next(&sector_extents);
-		if (!offset)
-			return -ENOSPC;
-		handle.cur->next_swap = offset;
-		error = write_page(handle.cur, handle.cur_swap, 1);
-		if (error)
-			goto out;
-		memset(handle.cur, 0, PAGE_SIZE);
-		handle.cur_swap = offset;
-		handle.k = 0;
-	}
- out:
-	return error;
-}
-
-static int flush_swap_writer(void)
-{
-	if (handle.cur && handle.cur_swap)
-		return write_page(handle.cur, handle.cur_swap, 1);
-	else
-		return -EINVAL;
-}
-
 static int swap_writer_finish(unsigned int flags, int error)
 {
 	if (!error) {
@@ -441,65 +318,6 @@ out_finish:
 	return error;
 }
 
-/**
- *	The following functions allow us to read data using a swap map
- *	in a file-alike way
- */
-
-static void release_swap_reader(void)
-{
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
-}
-
-static int get_swap_reader(unsigned int *flags_p)
-{
-	int error;
-
-	*flags_p = swsusp_header->flags;
-
-	if (!swsusp_header->image) /* how can this happen? */
-		return -EINVAL;
-
-	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
-	if (!handle.cur)
-		return -ENOMEM;
-
-	error = hib_bio_read_page(swsusp_header->image, handle.cur, 1);
-	if (error) {
-		release_swap_reader();
-		return error;
-	}
-	handle.k = 0;
-	return 0;
-}
-
-int swap_read_page(void *buf, int sync)
-{
-	sector_t offset;
-	int error;
-
-	if (!handle.cur)
-		return -EINVAL;
-	offset = handle.cur->entries[handle.k];
-	if (!offset)
-		return -EFAULT;
-	error = hib_bio_read_page(offset, buf, sync);
-	if (error)
-		return error;
-	if (++handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		handle.k = 0;
-		offset = handle.cur->next_swap;
-		if (!offset)
-			release_swap_reader();
-		else if (!error)
-			error = hib_bio_read_page(offset, handle.cur, 1);
-	}
-	return error;
-}
-
 static int swap_reader_finish(void)
 {
 	release_swap_reader();
@@ -586,7 +404,12 @@ int swsusp_read(unsigned int *flags_p)
 		return error < 0 ? error : -EFAULT;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = get_swap_reader(flags_p);
+	*flags_p = swsusp_header->flags;
+	if (!swsusp_header->image) { /* how can this happen? */
+		error = -EINVAL;
+		goto end;
+	}
+	error = get_swap_reader(flags_p, swsusp_header->image);
 	if (error)
 		goto end;
 	if (!error)
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
deleted file mode 100644
index 8e2eed4..0000000
--- a/kernel/power/swap.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * linux/kernel/power/swap.h
- *
- * This file provides declarations for functions and structures from
- * kernel/power/swap.c.
- *
- * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
- *
- * This file is released under the GPLv2.
- *
- */
-
-int swap_write_page(void *buf, int sync);
-int swap_read_page(void *buf, int sync);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 12/23] Hibernation: Move block i/o fns to block_io.c
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (22 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (29 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Move the functions that specifically deal with submitting I/O
to block_io.c. This helps us in working towards having a clean
separation between swap specific functions (which will be all
that will be in swap.c eventually) and low level block i/o
functions (block_io.c) that are/will be agnostic with regard to
the source of the storage. The block_io.c functions will thus
also be useable when support for storing an image in a generic
file (non swap) is added later.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |  199 ++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/block_io.h |   23 ++++++
 kernel/power/compress.c |    2 +-
 kernel/power/swap.c     |  203 +++--------------------------------------------
 kernel/power/swap.h     |   14 ---
 5 files changed, 236 insertions(+), 205 deletions(-)
 create mode 100644 kernel/power/block_io.h
 delete mode 100644 kernel/power/swap.h

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index aa239a2..5edcb08 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -13,6 +13,7 @@
 #include <linux/swap.h>
 
 #include "power.h"
+#include "extents.h"
 
 static struct bio *bio_chain;
 
@@ -102,3 +103,201 @@ int hib_wait_on_bio_chain(void)
 	bio_chain = NULL;
 	return ret;
 }
+
+/*
+ *	The swap map is a data structure used for keeping track of each page
+ *	written to a swap partition.  It consists of many swap_map_page
+ *	structures that contain each an array of MAP_PAGE_SIZE swap entries.
+ *	These structures are stored on the swap and linked together with the
+ *	help of the .next_swap member.
+ *
+ *	The swap map is created during suspend.  The swap map pages are
+ *	allocated and populated one at a time, so we only need one memory
+ *	page to set up the entire structure.
+ *
+ *	During resume we also only need to use one swap_map_page structure
+ *	at a time.
+ */
+
+#define MAP_PAGE_ENTRIES	(PAGE_SIZE / sizeof(sector_t) - 1)
+
+struct swap_map_page {
+	sector_t entries[MAP_PAGE_ENTRIES];
+	sector_t next_swap;
+};
+
+/**
+ *	The swap_map_handle structure is used for handling swap in
+ *	a file-alike way
+ */
+
+struct swap_map_handle {
+	struct swap_map_page *cur;
+	sector_t cur_swap;
+	sector_t first_sector;
+	unsigned int k;
+};
+
+static struct swap_map_handle handle;
+
+extern struct hib_extent_state sector_extents;
+
+/* Calculate the overhead needed for storing n pages */
+unsigned int hib_bio_overhead(unsigned int nr_pages)
+{
+	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+}
+
+/* Get the first sector of the image proper, for storing in the signature */
+sector_t hib_get_first_sector(void)
+{
+	return handle.first_sector;
+}
+
+/**
+ *	write_page - Write one page to given swap location.
+ *	@buf:		Address we're writing.
+ *	@offset:	Offset of the swap page we're writing to.
+ *	@sync:		Whether to force synchronous i/o.
+ */
+
+static int write_page(void *buf, sector_t offset, int sync)
+{
+	void *src;
+
+	if (!offset)
+		return -ENOSPC;
+
+	if (!sync) {
+		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+		if (src) {
+			memcpy(src, buf, PAGE_SIZE);
+		} else {
+			WARN_ON_ONCE(1);
+			sync = 1;	/* Go synchronous */
+			src = buf;
+		}
+	} else {
+		src = buf;
+	}
+	return hib_bio_write_page(offset, src, sync);
+}
+
+void release_swap_writer(void)
+{
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
+}
+
+int hib_bio_prepare_write(void)
+{
+	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
+
+	if (!handle.cur)
+		return -ENOMEM;
+
+	handle.cur_swap = hib_extent_next(&sector_extents);
+
+	if (!handle.cur_swap) {
+		release_swap_writer();
+		return -ENOSPC;
+	}
+
+	handle.k = 0;
+	handle.first_sector = handle.cur_swap;
+	return 0;
+}
+
+int swap_write_page(void *buf, int sync)
+{
+	int error = 0;
+	sector_t offset;
+
+	if (!handle.cur)
+		return -EINVAL;
+	offset = hib_extent_next(&sector_extents);
+	error = write_page(buf, offset, sync);
+	if (error)
+		return error;
+	handle.cur->entries[handle.k++] = offset;
+	if (handle.k >= MAP_PAGE_ENTRIES) {
+		error = hib_wait_on_bio_chain();
+		if (error)
+			goto out;
+		offset = hib_extent_next(&sector_extents);
+		if (!offset)
+			return -ENOSPC;
+		handle.cur->next_swap = offset;
+		error = write_page(handle.cur, handle.cur_swap, 1);
+		if (error)
+			goto out;
+		memset(handle.cur, 0, PAGE_SIZE);
+		handle.cur_swap = offset;
+		handle.k = 0;
+	}
+ out:
+	return error;
+}
+
+int flush_swap_writer(void)
+{
+	if (handle.cur && handle.cur_swap)
+		return write_page(handle.cur, handle.cur_swap, 1);
+	else
+		return -EINVAL;
+}
+
+/**
+ *	The following functions allow us to read data using a swap map
+ *	in a file-alike way
+ */
+
+void release_swap_reader(void)
+{
+	if (handle.cur)
+		free_page((unsigned long)handle.cur);
+	handle.cur = NULL;
+}
+
+int get_swap_reader(unsigned int *flags_p, sector_t first_page)
+{
+	int error;
+
+	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
+	if (!handle.cur)
+		return -ENOMEM;
+
+	error = hib_bio_read_page(first_page, handle.cur, 1);
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+	handle.k = 0;
+	return 0;
+}
+
+int swap_read_page(void *buf, int sync)
+{
+	sector_t offset;
+	int error;
+
+	if (!handle.cur)
+		return -EINVAL;
+	offset = handle.cur->entries[handle.k];
+	if (!offset)
+		return -EFAULT;
+	error = hib_bio_read_page(offset, buf, sync);
+	if (error)
+		return error;
+	if (++handle.k >= MAP_PAGE_ENTRIES) {
+		error = hib_wait_on_bio_chain();
+		handle.k = 0;
+		offset = handle.cur->next_swap;
+		if (!offset)
+			release_swap_reader();
+		else if (!error)
+			error = hib_bio_read_page(offset, handle.cur, 1);
+	}
+	return error;
+}
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
new file mode 100644
index 0000000..2f91d6d
--- /dev/null
+++ b/kernel/power/block_io.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
+ * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
+ *
+ * This file is released under the GPLv2.
+ */
+
+/* Low level routines */
+int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
+int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
+int hib_wait_on_bio_chain(void);
+
+unsigned int hib_bio_overhead(unsigned int nr_pages);
+sector_t hib_get_first_sector(void);
+extern struct hib_extent_state sector_extents;
+void release_swap_writer(void);
+int hib_bio_prepare_write(void);
+int flush_swap_writer(void);
+int swap_write_page(void *buf, int sync);
+int get_swap_reader(unsigned int *flags_p, sector_t first_page);
+void release_swap_reader(void);
+int swap_read_page(void *buf, int sync);
diff --git a/kernel/power/compress.c b/kernel/power/compress.c
index bb9b9ab..773f8d8 100644
--- a/kernel/power/compress.c
+++ b/kernel/power/compress.c
@@ -15,7 +15,7 @@
 #include <linux/vmalloc.h>
 
 #include "power.h"
-#include "swap.h"
+#include "block_io.h"
 
 /* We need to remember how much compressed data we need to read. */
 #define LZO_HEADER	sizeof(size_t)
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index d828fe9..178fd31 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -17,47 +17,11 @@
 
 #include "power.h"
 #include "compress.h"
-#include "swap.h"
 #include "extents.h"
+#include "block_io.h"
 
 #define SWSUSP_SIG	"S1SUSPEND"
 
-/*
- *	The swap map is a data structure used for keeping track of each page
- *	written to a swap partition.  It consists of many swap_map_page
- *	structures that contain each an array of MAP_PAGE_ENTRIES swap entries.
- *	These structures are stored on the swap and linked together with the
- *	help of the .next_swap member.
- *
- *	The swap map is created during suspend.  The swap map pages are
- *	allocated and populated one at a time, so we only need one memory
- *	page to set up the entire structure.
- *
- *	During resume we also only need to use one swap_map_page structure
- *	at a time.
- */
-
-#define MAP_PAGE_ENTRIES	(PAGE_SIZE / sizeof(sector_t) - 1)
-
-struct swap_map_page {
-	sector_t entries[MAP_PAGE_ENTRIES];
-	sector_t next_swap;
-};
-
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	sector_t cur_swap;
-	sector_t first_sector;
-	unsigned int k;
-};
-
-static struct swap_map_handle handle;
-
 static unsigned short root_swap = 0xffff;
 
 struct swsusp_header {
@@ -72,7 +36,7 @@ struct swsusp_header {
 static struct swsusp_header *swsusp_header;
 
 static struct hib_extent_state swap_extents;
-static struct hib_extent_state sector_extents;
+struct hib_extent_state sector_extents;
 
 /**
  *	alloc_swapdev_block - allocate a swap page and register that it has
@@ -121,7 +85,7 @@ static int allocate_swap(unsigned int nr_pages, unsigned int flags)
 	unsigned int free_swap = count_swap_pages(root_swap, 1);
 
 	nr_pages += compress_extra_pages(nr_pages, flags);
-	nr_pages += DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+	nr_pages += hib_bio_overhead(nr_pages);
 
 	pr_debug("PM: Free swap pages: %u\n", free_swap);
 	if (free_swap < nr_pages)
@@ -179,7 +143,7 @@ static int mark_swapfiles(unsigned int flags)
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
 		memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
 		swsusp_header->write_speed = write_speed;
-		swsusp_header->image = handle.first_sector;
+		swsusp_header->image = hib_get_first_sector();
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
 					swsusp_header, 1);
@@ -217,42 +181,6 @@ static int swsusp_swap_check(void)
 	return res;
 }
 
-/**
- *	write_page - Write one page to given swap location.
- *	@buf:		Address we're writing.
- *	@offset:	Offset of the swap page we're writing to.
- *	@sync:		Whether to force synchronous i/o.
- */
-
-static int write_page(void *buf, sector_t offset, int sync)
-{
-	void *src;
-
-	if (!offset)
-		return -ENOSPC;
-
-	if (!sync) {
-		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-		if (src) {
-			memcpy(src, buf, PAGE_SIZE);
-		} else {
-			WARN_ON_ONCE(1);
-			sync = 1;	/* Go synchronous */
-			src = buf;
-		}
-	} else {
-		src = buf;
-	}
-	return hib_bio_write_page(offset, src, sync);
-}
-
-static void release_swap_writer(void)
-{
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
-}
-
 static int get_swap_writer(unsigned long pages, unsigned int flags)
 {
 	int ret;
@@ -264,70 +192,19 @@ static int get_swap_writer(unsigned long pages, unsigned int flags)
 					"swapon -a.\n");
 		return ret;
 	}
-	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
-	if (!handle.cur) {
-		ret = -ENOMEM;
-		goto err_close;
-	}
 	if (!allocate_swap(pages, flags)) {
 		printk(KERN_ERR "PM: Not enough free swap\n");
 		ret = -ENOSPC;
 		goto err_close;
 	}
-	handle.cur_swap = hib_extent_next(&sector_extents);
-	if (!handle.cur_swap) {
-		ret = -ENOSPC;
-		goto err_rel;
-	}
-	handle.k = 0;
-	handle.first_sector = handle.cur_swap;
-	return 0;
-err_rel:
-	release_swap_writer();
+	ret = hib_bio_prepare_write();
+	if (!ret)
+		return 0;
 err_close:
 	swsusp_close(FMODE_WRITE);
 	return ret;
 }
 
-int swap_write_page(void *buf, int sync)
-{
-	int error = 0;
-	sector_t offset;
-
-	if (!handle.cur)
-		return -EINVAL;
-	offset = hib_extent_next(&sector_extents);
-	error = write_page(buf, offset, sync);
-	if (error)
-		return error;
-	handle.cur->entries[handle.k++] = offset;
-	if (handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		if (error)
-			goto out;
-		offset = hib_extent_next(&sector_extents);
-		if (!offset)
-			return -ENOSPC;
-		handle.cur->next_swap = offset;
-		error = write_page(handle.cur, handle.cur_swap, 1);
-		if (error)
-			goto out;
-		memset(handle.cur, 0, PAGE_SIZE);
-		handle.cur_swap = offset;
-		handle.k = 0;
-	}
- out:
-	return error;
-}
-
-static int flush_swap_writer(void)
-{
-	if (handle.cur && handle.cur_swap)
-		return write_page(handle.cur, handle.cur_swap, 1);
-	else
-		return -EINVAL;
-}
-
 static int swap_writer_finish(unsigned int flags, int error)
 {
 	if (!error) {
@@ -441,65 +318,6 @@ out_finish:
 	return error;
 }
 
-/**
- *	The following functions allow us to read data using a swap map
- *	in a file-alike way
- */
-
-static void release_swap_reader(void)
-{
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
-}
-
-static int get_swap_reader(unsigned int *flags_p)
-{
-	int error;
-
-	*flags_p = swsusp_header->flags;
-
-	if (!swsusp_header->image) /* how can this happen? */
-		return -EINVAL;
-
-	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
-	if (!handle.cur)
-		return -ENOMEM;
-
-	error = hib_bio_read_page(swsusp_header->image, handle.cur, 1);
-	if (error) {
-		release_swap_reader();
-		return error;
-	}
-	handle.k = 0;
-	return 0;
-}
-
-int swap_read_page(void *buf, int sync)
-{
-	sector_t offset;
-	int error;
-
-	if (!handle.cur)
-		return -EINVAL;
-	offset = handle.cur->entries[handle.k];
-	if (!offset)
-		return -EFAULT;
-	error = hib_bio_read_page(offset, buf, sync);
-	if (error)
-		return error;
-	if (++handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		handle.k = 0;
-		offset = handle.cur->next_swap;
-		if (!offset)
-			release_swap_reader();
-		else if (!error)
-			error = hib_bio_read_page(offset, handle.cur, 1);
-	}
-	return error;
-}
-
 static int swap_reader_finish(void)
 {
 	release_swap_reader();
@@ -586,7 +404,12 @@ int swsusp_read(unsigned int *flags_p)
 		return error < 0 ? error : -EFAULT;
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
-	error = get_swap_reader(flags_p);
+	*flags_p = swsusp_header->flags;
+	if (!swsusp_header->image) { /* how can this happen? */
+		error = -EINVAL;
+		goto end;
+	}
+	error = get_swap_reader(flags_p, swsusp_header->image);
 	if (error)
 		goto end;
 	if (!error)
diff --git a/kernel/power/swap.h b/kernel/power/swap.h
deleted file mode 100644
index 8e2eed4..0000000
--- a/kernel/power/swap.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * linux/kernel/power/swap.h
- *
- * This file provides declarations for functions and structures from
- * kernel/power/swap.c.
- *
- * Copyright (C) 2010 Nigel Cunningham <nigel@tuxonice.net>
- *
- * This file is released under the GPLv2.
- *
- */
-
-int swap_write_page(void *buf, int sync);
-int swap_read_page(void *buf, int sync);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 13/23] Hibernation: Partial page I/O support.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (25 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-10-13  7:10   ` Pavel Machek
  2010-10-13  7:10   ` Pavel Machek
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (26 subsequent siblings)
  53 siblings, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add functions that can be used for coalescing and splitting buffers
that are smaller than PAGE_SIZE. These functions provide no method
of determining where the boundaries of the smaller buffers are to
be found - that is the caller's problem.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/block_io.h |    4 ++
 2 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 5edcb08..bf6129b 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -17,6 +17,11 @@
 
 static struct bio *bio_chain;
 
+static char *hib_ppio_buffer;
+static int hib_ppio_buffer_posn;
+int hib_prepare_buffer(void);
+void hib_free_buffer(void);
+
 /**
  *	submit - submit BIO request.
  *	@rw:	READ or WRITE.
@@ -301,3 +306,88 @@ int swap_read_page(void *buf, int sync)
 	}
 	return error;
 }
+
+/* Part Page I/O functions */
+static char *hib_ppio_buffer;
+static int hib_ppio_buffer_posn;
+
+int hib_prepare_buffer(void)
+{
+	hib_ppio_buffer = (char *)__get_free_page(__GFP_WAIT);
+	hib_ppio_buffer_posn = 0;
+	return hib_ppio_buffer ? 0 : -ENOMEM;
+}
+
+void hib_free_buffer(void)
+{
+	if (!hib_ppio_buffer)
+		return;
+
+	free_page((unsigned long) hib_ppio_buffer);
+	hib_ppio_buffer = NULL;
+}
+
+int hib_flush_write_buffer(void)
+{
+	return hib_ppio_buffer_posn ? swap_write_page(hib_ppio_buffer, 0) : 0;
+}
+
+int hib_write_buffer(char *buffer, int buffer_size)
+{
+	int bytes_left = buffer_size, result = 0;
+
+	while (bytes_left) {
+		char *from = buffer + buffer_size - bytes_left;
+		char *to = hib_ppio_buffer + hib_ppio_buffer_posn;
+		int capacity = PAGE_SIZE - hib_ppio_buffer_posn;
+
+		if (bytes_left <= capacity) {
+			memcpy(to, from, bytes_left);
+			hib_ppio_buffer_posn += bytes_left;
+			return 0;
+		}
+
+		/* Complete this page and start a new one */
+		memcpy(to, from, capacity);
+		bytes_left -= capacity;
+
+		result = swap_write_page(hib_ppio_buffer, 0);
+		if (result)
+			return result;
+
+		hib_ppio_buffer_posn = 0;
+	}
+
+	return 0;
+}
+
+int hib_read_buffer(char *buffer, int buffer_size)
+{
+	int bytes_left = buffer_size, result = 0;
+
+	while (bytes_left) {
+		char *to = buffer + buffer_size - bytes_left;
+		char *from = hib_ppio_buffer + hib_ppio_buffer_posn;
+		int capacity = PAGE_SIZE - hib_ppio_buffer_posn;
+
+		if (bytes_left <= capacity) {
+			memcpy(to, from, bytes_left);
+			hib_ppio_buffer_posn += bytes_left;
+			return 0;
+		}
+
+		/* Complete this page and start a new one */
+		memcpy(to, from, capacity);
+		bytes_left -= capacity;
+
+		result = swap_read_page(hib_ppio_buffer, 1);
+		if (result) {
+			printk("swap_read_page returned %d.\n", result);
+			return result;
+		}
+
+		hib_ppio_buffer_posn = 0;
+	}
+
+	return 0;
+}
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
index 2f91d6d..ac378c5 100644
--- a/kernel/power/block_io.h
+++ b/kernel/power/block_io.h
@@ -21,3 +21,7 @@ int swap_write_page(void *buf, int sync);
 int get_swap_reader(unsigned int *flags_p, sector_t first_page);
 void release_swap_reader(void);
 int swap_read_page(void *buf, int sync);
+int hib_flush_write_buffer(void);
+
+int hib_write_buffer(char *buffer, int len);
+int hib_read_buffer(char *buffer, int len);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 13/23] Hibernation: Partial page I/O support.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (26 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 13/23] Hibernation: Partial page I/O support Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 14/23] Hibernation: Store block extents at start of image Nigel Cunningham
                   ` (25 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add functions that can be used for coalescing and splitting buffers
that are smaller than PAGE_SIZE. These functions provide no method
of determining where the boundaries of the smaller buffers are to
be found - that is the caller's problem.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/block_io.h |    4 ++
 2 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 5edcb08..bf6129b 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -17,6 +17,11 @@
 
 static struct bio *bio_chain;
 
+static char *hib_ppio_buffer;
+static int hib_ppio_buffer_posn;
+int hib_prepare_buffer(void);
+void hib_free_buffer(void);
+
 /**
  *	submit - submit BIO request.
  *	@rw:	READ or WRITE.
@@ -301,3 +306,88 @@ int swap_read_page(void *buf, int sync)
 	}
 	return error;
 }
+
+/* Part Page I/O functions */
+static char *hib_ppio_buffer;
+static int hib_ppio_buffer_posn;
+
+int hib_prepare_buffer(void)
+{
+	hib_ppio_buffer = (char *)__get_free_page(__GFP_WAIT);
+	hib_ppio_buffer_posn = 0;
+	return hib_ppio_buffer ? 0 : -ENOMEM;
+}
+
+void hib_free_buffer(void)
+{
+	if (!hib_ppio_buffer)
+		return;
+
+	free_page((unsigned long) hib_ppio_buffer);
+	hib_ppio_buffer = NULL;
+}
+
+int hib_flush_write_buffer(void)
+{
+	return hib_ppio_buffer_posn ? swap_write_page(hib_ppio_buffer, 0) : 0;
+}
+
+int hib_write_buffer(char *buffer, int buffer_size)
+{
+	int bytes_left = buffer_size, result = 0;
+
+	while (bytes_left) {
+		char *from = buffer + buffer_size - bytes_left;
+		char *to = hib_ppio_buffer + hib_ppio_buffer_posn;
+		int capacity = PAGE_SIZE - hib_ppio_buffer_posn;
+
+		if (bytes_left <= capacity) {
+			memcpy(to, from, bytes_left);
+			hib_ppio_buffer_posn += bytes_left;
+			return 0;
+		}
+
+		/* Complete this page and start a new one */
+		memcpy(to, from, capacity);
+		bytes_left -= capacity;
+
+		result = swap_write_page(hib_ppio_buffer, 0);
+		if (result)
+			return result;
+
+		hib_ppio_buffer_posn = 0;
+	}
+
+	return 0;
+}
+
+int hib_read_buffer(char *buffer, int buffer_size)
+{
+	int bytes_left = buffer_size, result = 0;
+
+	while (bytes_left) {
+		char *to = buffer + buffer_size - bytes_left;
+		char *from = hib_ppio_buffer + hib_ppio_buffer_posn;
+		int capacity = PAGE_SIZE - hib_ppio_buffer_posn;
+
+		if (bytes_left <= capacity) {
+			memcpy(to, from, bytes_left);
+			hib_ppio_buffer_posn += bytes_left;
+			return 0;
+		}
+
+		/* Complete this page and start a new one */
+		memcpy(to, from, capacity);
+		bytes_left -= capacity;
+
+		result = swap_read_page(hib_ppio_buffer, 1);
+		if (result) {
+			printk("swap_read_page returned %d.\n", result);
+			return result;
+		}
+
+		hib_ppio_buffer_posn = 0;
+	}
+
+	return 0;
+}
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
index 2f91d6d..ac378c5 100644
--- a/kernel/power/block_io.h
+++ b/kernel/power/block_io.h
@@ -21,3 +21,7 @@ int swap_write_page(void *buf, int sync);
 int get_swap_reader(unsigned int *flags_p, sector_t first_page);
 void release_swap_reader(void);
 int swap_read_page(void *buf, int sync);
+int hib_flush_write_buffer(void);
+
+int hib_write_buffer(char *buffer, int len);
+int hib_read_buffer(char *buffer, int len);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 14/23] Hibernation: Store block extents at start of image
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (27 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (24 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

This patch adds support for storing the list of extents being
used at the start of the image, prior to the header, in
preparation for switching from using swap map pages to these
extents, then removing the swap map pages.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   59 ++++++++++++++++++++++++++++++++-----
 kernel/power/extents.c  |   75 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/extents.h  |    5 +++
 3 files changed, 131 insertions(+), 8 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index bf6129b..89601d3 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -14,6 +14,7 @@
 
 #include "power.h"
 #include "extents.h"
+#include "block_io.h"
 
 static struct bio *bio_chain;
 
@@ -150,7 +151,9 @@ extern struct hib_extent_state sector_extents;
 /* Calculate the overhead needed for storing n pages */
 unsigned int hib_bio_overhead(unsigned int nr_pages)
 {
-	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES) +
+	       DIV_ROUND_UP(hib_extents_storage_needed(&sector_extents),
+			PAGE_SIZE);
 }
 
 /* Get the first sector of the image proper, for storing in the signature */
@@ -197,21 +200,34 @@ void release_swap_writer(void)
 
 int hib_bio_prepare_write(void)
 {
+	int result, result2;
+
 	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
 
 	if (!handle.cur)
 		return -ENOMEM;
 
-	handle.cur_swap = hib_extent_next(&sector_extents);
-
-	if (!handle.cur_swap) {
+	result = hib_prepare_buffer();
+	if (result) {
 		release_swap_writer();
-		return -ENOSPC;
+		return result;
 	}
 
+	handle.first_sector = hib_extent_current(&sector_extents);
+
+	result = hib_extents_store(&sector_extents);
+	result2 = hib_flush_write_buffer();
+
+	handle.cur_swap = hib_extent_next(&sector_extents);
 	handle.k = 0;
-	handle.first_sector = handle.cur_swap;
-	return 0;
+
+	if (!handle.cur_swap)
+		result = -ENOSPC;
+
+	if (result || result2)
+		release_swap_writer();
+
+	return result ? result : result2;
 }
 
 int swap_write_page(void *buf, int sync)
@@ -268,6 +284,7 @@ void release_swap_reader(void)
 int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 {
 	int error;
+	sector_t offset;
 
 	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
 	if (!handle.cur)
@@ -278,8 +295,34 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 		release_swap_reader();
 		return error;
 	}
+
+	error = hib_prepare_buffer();
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+
 	handle.k = 0;
-	return 0;
+
+	/* Bootstrap reading the extents */
+	memcpy(hib_ppio_buffer, handle.cur, PAGE_SIZE);
+	error = hib_extents_load(&sector_extents, 1);
+
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+
+	offset = hib_extent_next(&sector_extents);
+
+	/* Now read the first swap_map_page */
+	error = hib_bio_read_page(offset, handle.cur, 1);
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+
+	return error;
 }
 
 int swap_read_page(void *buf, int sync)
diff --git a/kernel/power/extents.c b/kernel/power/extents.c
index 172322d..75d2fb4 100644
--- a/kernel/power/extents.c
+++ b/kernel/power/extents.c
@@ -14,6 +14,7 @@
 
 #include <linux/slab.h>
 #include "extents.h"
+#include "block_io.h"
 
 int hib_extents_empty(struct hib_extent_state *pos)
 {
@@ -123,3 +124,77 @@ void hib_extents_clear(struct hib_extent_state *pos)
 		kfree(ext);
 	}
 }
+
+int hib_extents_storage_needed(struct hib_extent_state *pos)
+{
+	return sizeof(int) + pos->num_extents * 2 * sizeof(unsigned long);
+}
+
+int hib_extents_store(struct hib_extent_state *pos)
+{
+	struct rb_node *node;
+	struct hib_extent *ext;
+	int ret = hib_write_buffer((char *) &pos->num_extents, sizeof(int));
+
+	if (hib_extents_empty(pos))
+		return 0;
+
+	node = rb_first(&pos->root);
+	while (node) {
+		ext = container_of(node, struct hib_extent, node);
+		ret = hib_write_buffer((char *) &ext->start,
+				2 * sizeof(unsigned long));
+		if (ret)
+			return ret;
+		node = rb_next(node);
+	}
+
+	return 0;
+}
+
+int hib_extents_load(struct hib_extent_state *pos, int bootstrap)
+{
+	struct rb_node **new = &(pos->root.rb_node);
+	struct rb_node *parent = NULL;
+	struct hib_extent *existing, *adding;
+	int i;
+	int ret = hib_read_buffer((char *) &pos->num_extents, sizeof(int));
+
+	if (!pos->num_extents)
+		return 0;
+
+	for (i = 0; i < pos->num_extents; i++) {
+		adding = kzalloc(sizeof(struct hib_extent), GFP_KERNEL);
+		if (!adding)
+			return -ENOMEM;
+
+		ret = hib_read_buffer((char *) &adding->start,
+				2 * sizeof(unsigned long));
+		if (ret)
+			return ret;
+
+		/*
+		 * No need for some of the checks from inserting above -
+		 * they were done when preparing the image.
+		 */
+		while (*new) {
+			existing = container_of(*new, struct hib_extent, node);
+			parent = *new;
+			if (adding->end < existing->start)
+				new = &((*new)->rb_left);
+			else
+				new = &((*new)->rb_right);
+		}
+		rb_link_node(&adding->node, parent, new);
+		rb_insert_color(&adding->node, &pos->root);
+
+		if (bootstrap && !i) {
+			hib_reset_extent_pos(&sector_extents);
+
+			/* We have already read the first page */
+			hib_extent_next(&sector_extents);
+		}
+	}
+
+	return 0;
+}
diff --git a/kernel/power/extents.h b/kernel/power/extents.h
index 0b69b8e..4288f9e 100644
--- a/kernel/power/extents.h
+++ b/kernel/power/extents.h
@@ -33,3 +33,8 @@ unsigned long hib_extent_next(struct hib_extent_state *pos);
 int hib_extents_insert(struct hib_extent_state *pos, unsigned long value);
 void hib_extents_clear(struct hib_extent_state *pos);
 int hib_extents_empty(struct hib_extent_state *pos);
+
+/* Serialisation support */
+int hib_extents_storage_needed(struct hib_extent_state *pos);
+int hib_extents_store(struct hib_extent_state *pos);
+int hib_extents_load(struct hib_extent_state *pos, int bootstrap);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 14/23] Hibernation: Store block extents at start of image
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (28 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 14/23] Hibernation: Store block extents at start of image Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 15/23] Hibernation: Use block extents for reading image Nigel Cunningham
                   ` (23 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

This patch adds support for storing the list of extents being
used at the start of the image, prior to the header, in
preparation for switching from using swap map pages to these
extents, then removing the swap map pages.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   59 ++++++++++++++++++++++++++++++++-----
 kernel/power/extents.c  |   75 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel/power/extents.h  |    5 +++
 3 files changed, 131 insertions(+), 8 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index bf6129b..89601d3 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -14,6 +14,7 @@
 
 #include "power.h"
 #include "extents.h"
+#include "block_io.h"
 
 static struct bio *bio_chain;
 
@@ -150,7 +151,9 @@ extern struct hib_extent_state sector_extents;
 /* Calculate the overhead needed for storing n pages */
 unsigned int hib_bio_overhead(unsigned int nr_pages)
 {
-	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES);
+	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES) +
+	       DIV_ROUND_UP(hib_extents_storage_needed(&sector_extents),
+			PAGE_SIZE);
 }
 
 /* Get the first sector of the image proper, for storing in the signature */
@@ -197,21 +200,34 @@ void release_swap_writer(void)
 
 int hib_bio_prepare_write(void)
 {
+	int result, result2;
+
 	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
 
 	if (!handle.cur)
 		return -ENOMEM;
 
-	handle.cur_swap = hib_extent_next(&sector_extents);
-
-	if (!handle.cur_swap) {
+	result = hib_prepare_buffer();
+	if (result) {
 		release_swap_writer();
-		return -ENOSPC;
+		return result;
 	}
 
+	handle.first_sector = hib_extent_current(&sector_extents);
+
+	result = hib_extents_store(&sector_extents);
+	result2 = hib_flush_write_buffer();
+
+	handle.cur_swap = hib_extent_next(&sector_extents);
 	handle.k = 0;
-	handle.first_sector = handle.cur_swap;
-	return 0;
+
+	if (!handle.cur_swap)
+		result = -ENOSPC;
+
+	if (result || result2)
+		release_swap_writer();
+
+	return result ? result : result2;
 }
 
 int swap_write_page(void *buf, int sync)
@@ -268,6 +284,7 @@ void release_swap_reader(void)
 int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 {
 	int error;
+	sector_t offset;
 
 	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
 	if (!handle.cur)
@@ -278,8 +295,34 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 		release_swap_reader();
 		return error;
 	}
+
+	error = hib_prepare_buffer();
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+
 	handle.k = 0;
-	return 0;
+
+	/* Bootstrap reading the extents */
+	memcpy(hib_ppio_buffer, handle.cur, PAGE_SIZE);
+	error = hib_extents_load(&sector_extents, 1);
+
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+
+	offset = hib_extent_next(&sector_extents);
+
+	/* Now read the first swap_map_page */
+	error = hib_bio_read_page(offset, handle.cur, 1);
+	if (error) {
+		release_swap_reader();
+		return error;
+	}
+
+	return error;
 }
 
 int swap_read_page(void *buf, int sync)
diff --git a/kernel/power/extents.c b/kernel/power/extents.c
index 172322d..75d2fb4 100644
--- a/kernel/power/extents.c
+++ b/kernel/power/extents.c
@@ -14,6 +14,7 @@
 
 #include <linux/slab.h>
 #include "extents.h"
+#include "block_io.h"
 
 int hib_extents_empty(struct hib_extent_state *pos)
 {
@@ -123,3 +124,77 @@ void hib_extents_clear(struct hib_extent_state *pos)
 		kfree(ext);
 	}
 }
+
+int hib_extents_storage_needed(struct hib_extent_state *pos)
+{
+	return sizeof(int) + pos->num_extents * 2 * sizeof(unsigned long);
+}
+
+int hib_extents_store(struct hib_extent_state *pos)
+{
+	struct rb_node *node;
+	struct hib_extent *ext;
+	int ret = hib_write_buffer((char *) &pos->num_extents, sizeof(int));
+
+	if (hib_extents_empty(pos))
+		return 0;
+
+	node = rb_first(&pos->root);
+	while (node) {
+		ext = container_of(node, struct hib_extent, node);
+		ret = hib_write_buffer((char *) &ext->start,
+				2 * sizeof(unsigned long));
+		if (ret)
+			return ret;
+		node = rb_next(node);
+	}
+
+	return 0;
+}
+
+int hib_extents_load(struct hib_extent_state *pos, int bootstrap)
+{
+	struct rb_node **new = &(pos->root.rb_node);
+	struct rb_node *parent = NULL;
+	struct hib_extent *existing, *adding;
+	int i;
+	int ret = hib_read_buffer((char *) &pos->num_extents, sizeof(int));
+
+	if (!pos->num_extents)
+		return 0;
+
+	for (i = 0; i < pos->num_extents; i++) {
+		adding = kzalloc(sizeof(struct hib_extent), GFP_KERNEL);
+		if (!adding)
+			return -ENOMEM;
+
+		ret = hib_read_buffer((char *) &adding->start,
+				2 * sizeof(unsigned long));
+		if (ret)
+			return ret;
+
+		/*
+		 * No need for some of the checks from inserting above -
+		 * they were done when preparing the image.
+		 */
+		while (*new) {
+			existing = container_of(*new, struct hib_extent, node);
+			parent = *new;
+			if (adding->end < existing->start)
+				new = &((*new)->rb_left);
+			else
+				new = &((*new)->rb_right);
+		}
+		rb_link_node(&adding->node, parent, new);
+		rb_insert_color(&adding->node, &pos->root);
+
+		if (bootstrap && !i) {
+			hib_reset_extent_pos(&sector_extents);
+
+			/* We have already read the first page */
+			hib_extent_next(&sector_extents);
+		}
+	}
+
+	return 0;
+}
diff --git a/kernel/power/extents.h b/kernel/power/extents.h
index 0b69b8e..4288f9e 100644
--- a/kernel/power/extents.h
+++ b/kernel/power/extents.h
@@ -33,3 +33,8 @@ unsigned long hib_extent_next(struct hib_extent_state *pos);
 int hib_extents_insert(struct hib_extent_state *pos, unsigned long value);
 void hib_extents_clear(struct hib_extent_state *pos);
 int hib_extents_empty(struct hib_extent_state *pos);
+
+/* Serialisation support */
+int hib_extents_storage_needed(struct hib_extent_state *pos);
+int hib_extents_store(struct hib_extent_state *pos);
+int hib_extents_load(struct hib_extent_state *pos, int bootstrap);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 15/23] Hibernation: Use block extents for reading image
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (30 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 15/23] Hibernation: Use block extents for reading image Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 16/23] Remove first_sector from swap_map_handle Nigel Cunningham
                   ` (21 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Switch from using swap map pages to using block extents for
knowing where the next page needs to be read from.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 89601d3..f2bc044 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -332,7 +332,7 @@ int swap_read_page(void *buf, int sync)
 
 	if (!handle.cur)
 		return -EINVAL;
-	offset = handle.cur->entries[handle.k];
+	offset = hib_extent_next(&sector_extents);
 	if (!offset)
 		return -EFAULT;
 	error = hib_bio_read_page(offset, buf, sync);
@@ -341,7 +341,7 @@ int swap_read_page(void *buf, int sync)
 	if (++handle.k >= MAP_PAGE_ENTRIES) {
 		error = hib_wait_on_bio_chain();
 		handle.k = 0;
-		offset = handle.cur->next_swap;
+		offset = hib_extent_next(&sector_extents);
 		if (!offset)
 			release_swap_reader();
 		else if (!error)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 15/23] Hibernation: Use block extents for reading image
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (29 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (22 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Switch from using swap map pages to using block extents for
knowing where the next page needs to be read from.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 89601d3..f2bc044 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -332,7 +332,7 @@ int swap_read_page(void *buf, int sync)
 
 	if (!handle.cur)
 		return -EINVAL;
-	offset = handle.cur->entries[handle.k];
+	offset = hib_extent_next(&sector_extents);
 	if (!offset)
 		return -EFAULT;
 	error = hib_bio_read_page(offset, buf, sync);
@@ -341,7 +341,7 @@ int swap_read_page(void *buf, int sync)
 	if (++handle.k >= MAP_PAGE_ENTRIES) {
 		error = hib_wait_on_bio_chain();
 		handle.k = 0;
-		offset = handle.cur->next_swap;
+		offset = hib_extent_next(&sector_extents);
 		if (!offset)
 			release_swap_reader();
 		else if (!error)
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 16/23] Remove first_sector from swap_map_handle
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (31 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (20 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Remove the 'first_sector' variable from the swap_map_handle
struct. It will continue to be used whereas the other members
of the struct will be deleted in a following patch.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index f2bc044..e6709db 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -140,10 +140,10 @@ struct swap_map_page {
 struct swap_map_handle {
 	struct swap_map_page *cur;
 	sector_t cur_swap;
-	sector_t first_sector;
 	unsigned int k;
 };
 
+static sector_t first_sector;
 static struct swap_map_handle handle;
 
 extern struct hib_extent_state sector_extents;
@@ -159,7 +159,7 @@ unsigned int hib_bio_overhead(unsigned int nr_pages)
 /* Get the first sector of the image proper, for storing in the signature */
 sector_t hib_get_first_sector(void)
 {
-	return handle.first_sector;
+	return first_sector;
 }
 
 /**
@@ -213,7 +213,7 @@ int hib_bio_prepare_write(void)
 		return result;
 	}
 
-	handle.first_sector = hib_extent_current(&sector_extents);
+	first_sector = hib_extent_current(&sector_extents);
 
 	result = hib_extents_store(&sector_extents);
 	result2 = hib_flush_write_buffer();
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 16/23] Remove first_sector from swap_map_handle
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (32 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 16/23] Remove first_sector from swap_map_handle Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 17/23] Hibernation: Replace bio chain Nigel Cunningham
                   ` (19 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Remove the 'first_sector' variable from the swap_map_handle
struct. It will continue to be used whereas the other members
of the struct will be deleted in a following patch.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index f2bc044..e6709db 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -140,10 +140,10 @@ struct swap_map_page {
 struct swap_map_handle {
 	struct swap_map_page *cur;
 	sector_t cur_swap;
-	sector_t first_sector;
 	unsigned int k;
 };
 
+static sector_t first_sector;
 static struct swap_map_handle handle;
 
 extern struct hib_extent_state sector_extents;
@@ -159,7 +159,7 @@ unsigned int hib_bio_overhead(unsigned int nr_pages)
 /* Get the first sector of the image proper, for storing in the signature */
 sector_t hib_get_first_sector(void)
 {
-	return handle.first_sector;
+	return first_sector;
 }
 
 /**
@@ -213,7 +213,7 @@ int hib_bio_prepare_write(void)
 		return result;
 	}
 
-	handle.first_sector = hib_extent_current(&sector_extents);
+	first_sector = hib_extent_current(&sector_extents);
 
 	result = hib_extents_store(&sector_extents);
 	result2 = hib_flush_write_buffer();
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 17/23] Hibernation: Replace bio chain
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (33 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (18 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Replace the bio_chain concept with:
(1) simple atomic_t recording how many pages are in flight
(2) a wait queue for waiting for all I/O to complete
(3) a custom completion routine that frees bio structs and pages used
    for async writes as they complete, undates the atomic_t and
    wakes any waiters.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   77 ++++++++++++++++++++++++++++------------------
 1 files changed, 47 insertions(+), 30 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index e6709db..24b6db5 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -16,23 +16,61 @@
 #include "extents.h"
 #include "block_io.h"
 
-static struct bio *bio_chain;
-
 static char *hib_ppio_buffer;
 static int hib_ppio_buffer_posn;
 int hib_prepare_buffer(void);
 void hib_free_buffer(void);
 
+static atomic_t hib_io_in_progress;
+static DECLARE_WAIT_QUEUE_HEAD(num_in_progress_wait);
+
+/**
+ * hib_end_bio - bio completion function.
+ * @bio: bio that has completed.
+ * @err: Error value. Yes, like end_swap_bio_read, we ignore it.
+ *
+ * Function called by the block driver from interrupt context when I/O is
+ * completed. If we were writing the page, we want to free it and will have
+ * set bio->bi_private to the parameter we should use in telling the page
+ * allocation accounting code what the page was allocated for. If we're
+ * reading the page, it will be in the singly linked list made from
+ * page->private pointers.
+ **/
+static void hib_end_bio(struct bio *bio, int err)
+{
+	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	struct page *page = bio->bi_io_vec[0].bv_page;
+
+	if (!uptodate) {
+		SetPageError(page);
+		ClearPageUptodate(page);
+		printk(KERN_ALERT "I/O on swap-device (%u:%u:%Lu)\n",
+				imajor(bio->bi_bdev->bd_inode),
+				iminor(bio->bi_bdev->bd_inode),
+				(unsigned long long)bio->bi_sector);
+	} else {
+		SetPageUptodate(page);
+	}
+	unlock_page(page);
+	bio_put(bio);
+
+	if (bio->bi_private)
+		__free_page(page);
+
+	atomic_dec(&hib_io_in_progress);
+	wake_up(&num_in_progress_wait);
+}
+
 /**
  *	submit - submit BIO request.
  *	@rw:	READ or WRITE.
  *	@off	physical offset of page.
  *	@page:	page we're reading or writing.
- *	@bio_chain: list of pending biod (for async reading)
+ *	@sync:	whether the i/o should be done synchronously
  *
  *	Straight from the textbook - allocate and initialize the bio.
  *	If we're reading, make sure the page is marked as dirty.
- *	Then submit it and, if @bio_chain == NULL, wait.
+ *	Then submit it and, if @sync, wait.
  */
 static int submit(int rw, struct block_device *bdev, sector_t sector,
 		struct page *page, int sync)
@@ -43,7 +81,8 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
 	bio->bi_sector = sector;
 	bio->bi_bdev = bdev;
-	bio->bi_end_io = end_swap_bio_read;
+	bio->bi_private = (void *) (rw && !sync);
+	bio->bi_end_io = hib_end_bio;
 
 	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
 		printk(KERN_ERR "PM: Adding page to bio failed at %llu\n",
@@ -54,6 +93,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 
 	lock_page(page);
 	bio_get(bio);
+	atomic_inc(&hib_io_in_progress);
 
 	if (sync) {
 		submit_bio(bio_rw, bio);
@@ -64,8 +104,6 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	} else {
 		if (rw == READ)
 			get_page(page);	/* These pages are freed later */
-		bio->bi_private = bio_chain;
-		bio_chain = bio;
 		submit_bio(bio_rw, bio);
 	}
 	return 0;
@@ -85,29 +123,8 @@ int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 
 int hib_wait_on_bio_chain(void)
 {
-	struct bio *bio;
-	struct bio *next_bio;
-	int ret = 0;
-
-	if (bio_chain == NULL)
-		return 0;
-
-	bio = bio_chain;
-
-	while (bio) {
-		struct page *page;
-
-		next_bio = bio->bi_private;
-		page = bio->bi_io_vec[0].bv_page;
-		wait_on_page_locked(page);
-		if (!PageUptodate(page) || PageError(page))
-			ret = -EIO;
-		put_page(page);
-		bio_put(bio);
-		bio = next_bio;
-	}
-	bio_chain = NULL;
-	return ret;
+	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
+	return 0;
 }
 
 /*
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 17/23] Hibernation: Replace bio chain
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (34 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 17/23] Hibernation: Replace bio chain Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 18/23] Hibernation: Remove swap_map_pages Nigel Cunningham
                   ` (17 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Replace the bio_chain concept with:
(1) simple atomic_t recording how many pages are in flight
(2) a wait queue for waiting for all I/O to complete
(3) a custom completion routine that frees bio structs and pages used
    for async writes as they complete, undates the atomic_t and
    wakes any waiters.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   77 ++++++++++++++++++++++++++++------------------
 1 files changed, 47 insertions(+), 30 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index e6709db..24b6db5 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -16,23 +16,61 @@
 #include "extents.h"
 #include "block_io.h"
 
-static struct bio *bio_chain;
-
 static char *hib_ppio_buffer;
 static int hib_ppio_buffer_posn;
 int hib_prepare_buffer(void);
 void hib_free_buffer(void);
 
+static atomic_t hib_io_in_progress;
+static DECLARE_WAIT_QUEUE_HEAD(num_in_progress_wait);
+
+/**
+ * hib_end_bio - bio completion function.
+ * @bio: bio that has completed.
+ * @err: Error value. Yes, like end_swap_bio_read, we ignore it.
+ *
+ * Function called by the block driver from interrupt context when I/O is
+ * completed. If we were writing the page, we want to free it and will have
+ * set bio->bi_private to the parameter we should use in telling the page
+ * allocation accounting code what the page was allocated for. If we're
+ * reading the page, it will be in the singly linked list made from
+ * page->private pointers.
+ **/
+static void hib_end_bio(struct bio *bio, int err)
+{
+	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	struct page *page = bio->bi_io_vec[0].bv_page;
+
+	if (!uptodate) {
+		SetPageError(page);
+		ClearPageUptodate(page);
+		printk(KERN_ALERT "I/O on swap-device (%u:%u:%Lu)\n",
+				imajor(bio->bi_bdev->bd_inode),
+				iminor(bio->bi_bdev->bd_inode),
+				(unsigned long long)bio->bi_sector);
+	} else {
+		SetPageUptodate(page);
+	}
+	unlock_page(page);
+	bio_put(bio);
+
+	if (bio->bi_private)
+		__free_page(page);
+
+	atomic_dec(&hib_io_in_progress);
+	wake_up(&num_in_progress_wait);
+}
+
 /**
  *	submit - submit BIO request.
  *	@rw:	READ or WRITE.
  *	@off	physical offset of page.
  *	@page:	page we're reading or writing.
- *	@bio_chain: list of pending biod (for async reading)
+ *	@sync:	whether the i/o should be done synchronously
  *
  *	Straight from the textbook - allocate and initialize the bio.
  *	If we're reading, make sure the page is marked as dirty.
- *	Then submit it and, if @bio_chain == NULL, wait.
+ *	Then submit it and, if @sync, wait.
  */
 static int submit(int rw, struct block_device *bdev, sector_t sector,
 		struct page *page, int sync)
@@ -43,7 +81,8 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
 	bio->bi_sector = sector;
 	bio->bi_bdev = bdev;
-	bio->bi_end_io = end_swap_bio_read;
+	bio->bi_private = (void *) (rw && !sync);
+	bio->bi_end_io = hib_end_bio;
 
 	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
 		printk(KERN_ERR "PM: Adding page to bio failed at %llu\n",
@@ -54,6 +93,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 
 	lock_page(page);
 	bio_get(bio);
+	atomic_inc(&hib_io_in_progress);
 
 	if (sync) {
 		submit_bio(bio_rw, bio);
@@ -64,8 +104,6 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	} else {
 		if (rw == READ)
 			get_page(page);	/* These pages are freed later */
-		bio->bi_private = bio_chain;
-		bio_chain = bio;
 		submit_bio(bio_rw, bio);
 	}
 	return 0;
@@ -85,29 +123,8 @@ int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 
 int hib_wait_on_bio_chain(void)
 {
-	struct bio *bio;
-	struct bio *next_bio;
-	int ret = 0;
-
-	if (bio_chain == NULL)
-		return 0;
-
-	bio = bio_chain;
-
-	while (bio) {
-		struct page *page;
-
-		next_bio = bio->bi_private;
-		page = bio->bi_io_vec[0].bv_page;
-		wait_on_page_locked(page);
-		if (!PageUptodate(page) || PageError(page))
-			ret = -EIO;
-		put_page(page);
-		bio_put(bio);
-		bio = next_bio;
-	}
-	bio_chain = NULL;
-	return ret;
+	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
+	return 0;
 }
 
 /*
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 18/23] Hibernation: Remove swap_map_pages
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (36 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 18/23] Hibernation: Remove swap_map_pages Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 19/23] Hibernation: Remove wait_on_bio_chain result Nigel Cunningham
                   ` (15 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Stop storing swap_map pages in the image. This removes the need
for a wait_on_bio_chain every MAP_PAGE_ENTRIES pages and thus
allows the whole image to be written using async I/O.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   61 +++-------------------------------------------
 1 files changed, 4 insertions(+), 57 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 24b6db5..b068b5a 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -156,7 +156,6 @@ struct swap_map_page {
 
 struct swap_map_handle {
 	struct swap_map_page *cur;
-	sector_t cur_swap;
 	unsigned int k;
 };
 
@@ -168,8 +167,7 @@ extern struct hib_extent_state sector_extents;
 /* Calculate the overhead needed for storing n pages */
 unsigned int hib_bio_overhead(unsigned int nr_pages)
 {
-	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES) +
-	       DIV_ROUND_UP(hib_extents_storage_needed(&sector_extents),
+	return DIV_ROUND_UP(hib_extents_storage_needed(&sector_extents),
 			PAGE_SIZE);
 }
 
@@ -235,12 +233,8 @@ int hib_bio_prepare_write(void)
 	result = hib_extents_store(&sector_extents);
 	result2 = hib_flush_write_buffer();
 
-	handle.cur_swap = hib_extent_next(&sector_extents);
 	handle.k = 0;
 
-	if (!handle.cur_swap)
-		result = -ENOSPC;
-
 	if (result || result2)
 		release_swap_writer();
 
@@ -249,41 +243,17 @@ int hib_bio_prepare_write(void)
 
 int swap_write_page(void *buf, int sync)
 {
-	int error = 0;
 	sector_t offset;
 
 	if (!handle.cur)
 		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
-	error = write_page(buf, offset, sync);
-	if (error)
-		return error;
-	handle.cur->entries[handle.k++] = offset;
-	if (handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		if (error)
-			goto out;
-		offset = hib_extent_next(&sector_extents);
-		if (!offset)
-			return -ENOSPC;
-		handle.cur->next_swap = offset;
-		error = write_page(handle.cur, handle.cur_swap, 1);
-		if (error)
-			goto out;
-		memset(handle.cur, 0, PAGE_SIZE);
-		handle.cur_swap = offset;
-		handle.k = 0;
-	}
- out:
-	return error;
+	return write_page(buf, offset, sync);
 }
 
 int flush_swap_writer(void)
 {
-	if (handle.cur && handle.cur_swap)
-		return write_page(handle.cur, handle.cur_swap, 1);
-	else
-		return -EINVAL;
+	return hib_wait_on_bio_chain();
 }
 
 /**
@@ -301,7 +271,6 @@ void release_swap_reader(void)
 int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 {
 	int error;
-	sector_t offset;
 
 	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
 	if (!handle.cur)
@@ -330,41 +299,19 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 		return error;
 	}
 
-	offset = hib_extent_next(&sector_extents);
-
-	/* Now read the first swap_map_page */
-	error = hib_bio_read_page(offset, handle.cur, 1);
-	if (error) {
-		release_swap_reader();
-		return error;
-	}
-
 	return error;
 }
 
 int swap_read_page(void *buf, int sync)
 {
 	sector_t offset;
-	int error;
 
 	if (!handle.cur)
 		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
 	if (!offset)
 		return -EFAULT;
-	error = hib_bio_read_page(offset, buf, sync);
-	if (error)
-		return error;
-	if (++handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		handle.k = 0;
-		offset = hib_extent_next(&sector_extents);
-		if (!offset)
-			release_swap_reader();
-		else if (!error)
-			error = hib_bio_read_page(offset, handle.cur, 1);
-	}
-	return error;
+	return hib_bio_read_page(offset, buf, sync);
 }
 
 /* Part Page I/O functions */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 18/23] Hibernation: Remove swap_map_pages
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (35 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (16 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Stop storing swap_map pages in the image. This removes the need
for a wait_on_bio_chain every MAP_PAGE_ENTRIES pages and thus
allows the whole image to be written using async I/O.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   61 +++-------------------------------------------
 1 files changed, 4 insertions(+), 57 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 24b6db5..b068b5a 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -156,7 +156,6 @@ struct swap_map_page {
 
 struct swap_map_handle {
 	struct swap_map_page *cur;
-	sector_t cur_swap;
 	unsigned int k;
 };
 
@@ -168,8 +167,7 @@ extern struct hib_extent_state sector_extents;
 /* Calculate the overhead needed for storing n pages */
 unsigned int hib_bio_overhead(unsigned int nr_pages)
 {
-	return DIV_ROUND_UP(nr_pages, MAP_PAGE_ENTRIES) +
-	       DIV_ROUND_UP(hib_extents_storage_needed(&sector_extents),
+	return DIV_ROUND_UP(hib_extents_storage_needed(&sector_extents),
 			PAGE_SIZE);
 }
 
@@ -235,12 +233,8 @@ int hib_bio_prepare_write(void)
 	result = hib_extents_store(&sector_extents);
 	result2 = hib_flush_write_buffer();
 
-	handle.cur_swap = hib_extent_next(&sector_extents);
 	handle.k = 0;
 
-	if (!handle.cur_swap)
-		result = -ENOSPC;
-
 	if (result || result2)
 		release_swap_writer();
 
@@ -249,41 +243,17 @@ int hib_bio_prepare_write(void)
 
 int swap_write_page(void *buf, int sync)
 {
-	int error = 0;
 	sector_t offset;
 
 	if (!handle.cur)
 		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
-	error = write_page(buf, offset, sync);
-	if (error)
-		return error;
-	handle.cur->entries[handle.k++] = offset;
-	if (handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		if (error)
-			goto out;
-		offset = hib_extent_next(&sector_extents);
-		if (!offset)
-			return -ENOSPC;
-		handle.cur->next_swap = offset;
-		error = write_page(handle.cur, handle.cur_swap, 1);
-		if (error)
-			goto out;
-		memset(handle.cur, 0, PAGE_SIZE);
-		handle.cur_swap = offset;
-		handle.k = 0;
-	}
- out:
-	return error;
+	return write_page(buf, offset, sync);
 }
 
 int flush_swap_writer(void)
 {
-	if (handle.cur && handle.cur_swap)
-		return write_page(handle.cur, handle.cur_swap, 1);
-	else
-		return -EINVAL;
+	return hib_wait_on_bio_chain();
 }
 
 /**
@@ -301,7 +271,6 @@ void release_swap_reader(void)
 int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 {
 	int error;
-	sector_t offset;
 
 	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
 	if (!handle.cur)
@@ -330,41 +299,19 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 		return error;
 	}
 
-	offset = hib_extent_next(&sector_extents);
-
-	/* Now read the first swap_map_page */
-	error = hib_bio_read_page(offset, handle.cur, 1);
-	if (error) {
-		release_swap_reader();
-		return error;
-	}
-
 	return error;
 }
 
 int swap_read_page(void *buf, int sync)
 {
 	sector_t offset;
-	int error;
 
 	if (!handle.cur)
 		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
 	if (!offset)
 		return -EFAULT;
-	error = hib_bio_read_page(offset, buf, sync);
-	if (error)
-		return error;
-	if (++handle.k >= MAP_PAGE_ENTRIES) {
-		error = hib_wait_on_bio_chain();
-		handle.k = 0;
-		offset = hib_extent_next(&sector_extents);
-		if (!offset)
-			release_swap_reader();
-		else if (!error)
-			error = hib_bio_read_page(offset, handle.cur, 1);
-	}
-	return error;
+	return hib_bio_read_page(offset, buf, sync);
 }
 
 /* Part Page I/O functions */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 19/23] Hibernation: Remove wait_on_bio_chain result
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (38 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 19/23] Hibernation: Remove wait_on_bio_chain result Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (13 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

wait_on_bio_chain can't fail - make the result void instead
of int.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |    6 +++---
 kernel/power/block_io.h |    2 +-
 kernel/power/power.h    |    2 +-
 kernel/power/swap.c     |   14 +++-----------
 4 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index b068b5a..c154a92 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -121,10 +121,9 @@ int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 			virt_to_page(addr), sync);
 }
 
-int hib_wait_on_bio_chain(void)
+void hib_wait_on_bio_chain(void)
 {
 	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
-	return 0;
 }
 
 /*
@@ -253,7 +252,8 @@ int swap_write_page(void *buf, int sync)
 
 int flush_swap_writer(void)
 {
-	return hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
+	return 0;
 }
 
 /**
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
index ac378c5..1482060 100644
--- a/kernel/power/block_io.h
+++ b/kernel/power/block_io.h
@@ -9,7 +9,7 @@
 /* Low level routines */
 int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
 int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
-int hib_wait_on_bio_chain(void);
+void hib_wait_on_bio_chain(void);
 
 unsigned int hib_bio_overhead(unsigned int nr_pages);
 sector_t hib_get_first_sector(void);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 3c11987..9525b9c 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -156,7 +156,7 @@ extern struct block_device *hib_resume_bdev;
 
 extern int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
 extern int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
-extern int hib_wait_on_bio_chain(void);
+extern void hib_wait_on_bio_chain(void);
 
 struct timeval;
 /* kernel/power/swsusp.c */
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 178fd31..0a9715b 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -233,7 +233,6 @@ static int save_image(struct snapshot_handle *snapshot,
 	unsigned int m;
 	int ret;
 	int nr_pages;
-	int err2;
 	struct timeval start;
 	struct timeval stop;
 	int mps;
@@ -257,11 +256,9 @@ static int save_image(struct snapshot_handle *snapshot,
 		nr_pages++;
 	}
 	compress_write_finish(flags);
-	err2 = hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
 	if (!ret)
-		ret = err2;
-	if (!ret)
 		printk(KERN_CONT "\b\b\b\bdone\n");
 	else
 		printk(KERN_CONT "\n");
@@ -338,7 +335,6 @@ static int load_image(struct snapshot_handle *snapshot,
 	int error = 0;
 	struct timeval start;
 	struct timeval stop;
-	int err2;
 	unsigned nr_pages;
 	int mps;
 
@@ -357,17 +353,13 @@ static int load_image(struct snapshot_handle *snapshot,
 		if (error)
 			break;
 		if (snapshot->sync_read)
-			error = hib_wait_on_bio_chain();
-		if (error)
-			break;
+			hib_wait_on_bio_chain();
 		if (!(nr_pages % m))
 			printk("\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	err2 = hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
-	if (!error)
-		error = err2;
 	if (!error) {
 		printk("\b\b\b\bdone\n");
 		snapshot_write_finalize(snapshot);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 19/23] Hibernation: Remove wait_on_bio_chain result
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (39 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 20/23] Hibernation: Prepare for handle.cur removal Nigel Cunningham
                   ` (12 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

wait_on_bio_chain can't fail - make the result void instead
of int.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |    6 +++---
 kernel/power/block_io.h |    2 +-
 kernel/power/power.h    |    2 +-
 kernel/power/swap.c     |   14 +++-----------
 4 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index b068b5a..c154a92 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -121,10 +121,9 @@ int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 			virt_to_page(addr), sync);
 }
 
-int hib_wait_on_bio_chain(void)
+void hib_wait_on_bio_chain(void)
 {
 	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
-	return 0;
 }
 
 /*
@@ -253,7 +252,8 @@ int swap_write_page(void *buf, int sync)
 
 int flush_swap_writer(void)
 {
-	return hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
+	return 0;
 }
 
 /**
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
index ac378c5..1482060 100644
--- a/kernel/power/block_io.h
+++ b/kernel/power/block_io.h
@@ -9,7 +9,7 @@
 /* Low level routines */
 int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
 int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
-int hib_wait_on_bio_chain(void);
+void hib_wait_on_bio_chain(void);
 
 unsigned int hib_bio_overhead(unsigned int nr_pages);
 sector_t hib_get_first_sector(void);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 3c11987..9525b9c 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -156,7 +156,7 @@ extern struct block_device *hib_resume_bdev;
 
 extern int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
 extern int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
-extern int hib_wait_on_bio_chain(void);
+extern void hib_wait_on_bio_chain(void);
 
 struct timeval;
 /* kernel/power/swsusp.c */
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 178fd31..0a9715b 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -233,7 +233,6 @@ static int save_image(struct snapshot_handle *snapshot,
 	unsigned int m;
 	int ret;
 	int nr_pages;
-	int err2;
 	struct timeval start;
 	struct timeval stop;
 	int mps;
@@ -257,11 +256,9 @@ static int save_image(struct snapshot_handle *snapshot,
 		nr_pages++;
 	}
 	compress_write_finish(flags);
-	err2 = hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
 	if (!ret)
-		ret = err2;
-	if (!ret)
 		printk(KERN_CONT "\b\b\b\bdone\n");
 	else
 		printk(KERN_CONT "\n");
@@ -338,7 +335,6 @@ static int load_image(struct snapshot_handle *snapshot,
 	int error = 0;
 	struct timeval start;
 	struct timeval stop;
-	int err2;
 	unsigned nr_pages;
 	int mps;
 
@@ -357,17 +353,13 @@ static int load_image(struct snapshot_handle *snapshot,
 		if (error)
 			break;
 		if (snapshot->sync_read)
-			error = hib_wait_on_bio_chain();
-		if (error)
-			break;
+			hib_wait_on_bio_chain();
 		if (!(nr_pages % m))
 			printk("\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	err2 = hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
-	if (!error)
-		error = err2;
 	if (!error) {
 		printk("\b\b\b\bdone\n");
 		snapshot_write_finalize(snapshot);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 19/23] Hibernation: Remove wait_on_bio_chain result
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (37 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (14 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

wait_on_bio_chain can't fail - make the result void instead
of int.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |    6 +++---
 kernel/power/block_io.h |    2 +-
 kernel/power/power.h    |    2 +-
 kernel/power/swap.c     |   14 +++-----------
 4 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index b068b5a..c154a92 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -121,10 +121,9 @@ int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 			virt_to_page(addr), sync);
 }
 
-int hib_wait_on_bio_chain(void)
+void hib_wait_on_bio_chain(void)
 {
 	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
-	return 0;
 }
 
 /*
@@ -253,7 +252,8 @@ int swap_write_page(void *buf, int sync)
 
 int flush_swap_writer(void)
 {
-	return hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
+	return 0;
 }
 
 /**
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
index ac378c5..1482060 100644
--- a/kernel/power/block_io.h
+++ b/kernel/power/block_io.h
@@ -9,7 +9,7 @@
 /* Low level routines */
 int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
 int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
-int hib_wait_on_bio_chain(void);
+void hib_wait_on_bio_chain(void);
 
 unsigned int hib_bio_overhead(unsigned int nr_pages);
 sector_t hib_get_first_sector(void);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 3c11987..9525b9c 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -156,7 +156,7 @@ extern struct block_device *hib_resume_bdev;
 
 extern int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
 extern int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
-extern int hib_wait_on_bio_chain(void);
+extern void hib_wait_on_bio_chain(void);
 
 struct timeval;
 /* kernel/power/swsusp.c */
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 178fd31..0a9715b 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -233,7 +233,6 @@ static int save_image(struct snapshot_handle *snapshot,
 	unsigned int m;
 	int ret;
 	int nr_pages;
-	int err2;
 	struct timeval start;
 	struct timeval stop;
 	int mps;
@@ -257,11 +256,9 @@ static int save_image(struct snapshot_handle *snapshot,
 		nr_pages++;
 	}
 	compress_write_finish(flags);
-	err2 = hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
 	if (!ret)
-		ret = err2;
-	if (!ret)
 		printk(KERN_CONT "\b\b\b\bdone\n");
 	else
 		printk(KERN_CONT "\n");
@@ -338,7 +335,6 @@ static int load_image(struct snapshot_handle *snapshot,
 	int error = 0;
 	struct timeval start;
 	struct timeval stop;
-	int err2;
 	unsigned nr_pages;
 	int mps;
 
@@ -357,17 +353,13 @@ static int load_image(struct snapshot_handle *snapshot,
 		if (error)
 			break;
 		if (snapshot->sync_read)
-			error = hib_wait_on_bio_chain();
-		if (error)
-			break;
+			hib_wait_on_bio_chain();
 		if (!(nr_pages % m))
 			printk("\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
 	}
-	err2 = hib_wait_on_bio_chain();
+	hib_wait_on_bio_chain();
 	do_gettimeofday(&stop);
-	if (!error)
-		error = err2;
 	if (!error) {
 		printk("\b\b\b\bdone\n");
 		snapshot_write_finalize(snapshot);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 20/23] Hibernation: Prepare for handle.cur removal
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (40 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (11 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Prepare for the removal of handle.cur by stopping using
it in get_swap_reader.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index c154a92..4f46878 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -276,29 +276,29 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 	if (!handle.cur)
 		return -ENOMEM;
 
-	error = hib_bio_read_page(first_page, handle.cur, 1);
+	error = hib_prepare_buffer();
 	if (error) {
 		release_swap_reader();
 		return error;
 	}
 
-	error = hib_prepare_buffer();
+	/* Bootstrap reading the extents */
+	error = hib_bio_read_page(first_page, hib_ppio_buffer, 1);
 	if (error) {
 		release_swap_reader();
+		hib_free_buffer();
 		return error;
 	}
 
 	handle.k = 0;
 
-	/* Bootstrap reading the extents */
-	memcpy(hib_ppio_buffer, handle.cur, PAGE_SIZE);
 	error = hib_extents_load(&sector_extents, 1);
 
 	if (error) {
 		release_swap_reader();
-		return error;
 	}
 
+	hib_free_buffer();
 	return error;
 }
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 20/23] Hibernation: Prepare for handle.cur removal
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (41 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 20/23] Hibernation: Prepare for handle.cur removal Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 21/23] Hibernation: Remove swap_map structure Nigel Cunningham
                   ` (10 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Prepare for the removal of handle.cur by stopping using
it in get_swap_reader.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index c154a92..4f46878 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -276,29 +276,29 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 	if (!handle.cur)
 		return -ENOMEM;
 
-	error = hib_bio_read_page(first_page, handle.cur, 1);
+	error = hib_prepare_buffer();
 	if (error) {
 		release_swap_reader();
 		return error;
 	}
 
-	error = hib_prepare_buffer();
+	/* Bootstrap reading the extents */
+	error = hib_bio_read_page(first_page, hib_ppio_buffer, 1);
 	if (error) {
 		release_swap_reader();
+		hib_free_buffer();
 		return error;
 	}
 
 	handle.k = 0;
 
-	/* Bootstrap reading the extents */
-	memcpy(hib_ppio_buffer, handle.cur, PAGE_SIZE);
 	error = hib_extents_load(&sector_extents, 1);
 
 	if (error) {
 		release_swap_reader();
-		return error;
 	}
 
+	hib_free_buffer();
 	return error;
 }
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 21/23] Hibernation: Remove swap_map structure
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (42 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (9 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Remove the now unused swap_map structure and associated
swap_map_handle.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   56 -----------------------------------------------
 1 files changed, 0 insertions(+), 56 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 4f46878..f452650 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -126,40 +126,7 @@ void hib_wait_on_bio_chain(void)
 	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
 }
 
-/*
- *	The swap map is a data structure used for keeping track of each page
- *	written to a swap partition.  It consists of many swap_map_page
- *	structures that contain each an array of MAP_PAGE_SIZE swap entries.
- *	These structures are stored on the swap and linked together with the
- *	help of the .next_swap member.
- *
- *	The swap map is created during suspend.  The swap map pages are
- *	allocated and populated one at a time, so we only need one memory
- *	page to set up the entire structure.
- *
- *	During resume we also only need to use one swap_map_page structure
- *	at a time.
- */
-
-#define MAP_PAGE_ENTRIES	(PAGE_SIZE / sizeof(sector_t) - 1)
-
-struct swap_map_page {
-	sector_t entries[MAP_PAGE_ENTRIES];
-	sector_t next_swap;
-};
-
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	unsigned int k;
-};
-
 static sector_t first_sector;
-static struct swap_map_handle handle;
 
 extern struct hib_extent_state sector_extents;
 
@@ -207,20 +174,12 @@ static int write_page(void *buf, sector_t offset, int sync)
 
 void release_swap_writer(void)
 {
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
 }
 
 int hib_bio_prepare_write(void)
 {
 	int result, result2;
 
-	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
-
-	if (!handle.cur)
-		return -ENOMEM;
-
 	result = hib_prepare_buffer();
 	if (result) {
 		release_swap_writer();
@@ -232,8 +191,6 @@ int hib_bio_prepare_write(void)
 	result = hib_extents_store(&sector_extents);
 	result2 = hib_flush_write_buffer();
 
-	handle.k = 0;
-
 	if (result || result2)
 		release_swap_writer();
 
@@ -244,8 +201,6 @@ int swap_write_page(void *buf, int sync)
 {
 	sector_t offset;
 
-	if (!handle.cur)
-		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
 	return write_page(buf, offset, sync);
 }
@@ -263,19 +218,12 @@ int flush_swap_writer(void)
 
 void release_swap_reader(void)
 {
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
 }
 
 int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 {
 	int error;
 
-	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
-	if (!handle.cur)
-		return -ENOMEM;
-
 	error = hib_prepare_buffer();
 	if (error) {
 		release_swap_reader();
@@ -290,8 +238,6 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 		return error;
 	}
 
-	handle.k = 0;
-
 	error = hib_extents_load(&sector_extents, 1);
 
 	if (error) {
@@ -306,8 +252,6 @@ int swap_read_page(void *buf, int sync)
 {
 	sector_t offset;
 
-	if (!handle.cur)
-		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
 	if (!offset)
 		return -EFAULT;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 21/23] Hibernation: Remove swap_map structure
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (43 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 21/23] Hibernation: Remove swap_map structure Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 22/23] Hibernation: Remove now-empty routines Nigel Cunningham
                   ` (8 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Remove the now unused swap_map structure and associated
swap_map_handle.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   56 -----------------------------------------------
 1 files changed, 0 insertions(+), 56 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 4f46878..f452650 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -126,40 +126,7 @@ void hib_wait_on_bio_chain(void)
 	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
 }
 
-/*
- *	The swap map is a data structure used for keeping track of each page
- *	written to a swap partition.  It consists of many swap_map_page
- *	structures that contain each an array of MAP_PAGE_SIZE swap entries.
- *	These structures are stored on the swap and linked together with the
- *	help of the .next_swap member.
- *
- *	The swap map is created during suspend.  The swap map pages are
- *	allocated and populated one at a time, so we only need one memory
- *	page to set up the entire structure.
- *
- *	During resume we also only need to use one swap_map_page structure
- *	at a time.
- */
-
-#define MAP_PAGE_ENTRIES	(PAGE_SIZE / sizeof(sector_t) - 1)
-
-struct swap_map_page {
-	sector_t entries[MAP_PAGE_ENTRIES];
-	sector_t next_swap;
-};
-
-/**
- *	The swap_map_handle structure is used for handling swap in
- *	a file-alike way
- */
-
-struct swap_map_handle {
-	struct swap_map_page *cur;
-	unsigned int k;
-};
-
 static sector_t first_sector;
-static struct swap_map_handle handle;
 
 extern struct hib_extent_state sector_extents;
 
@@ -207,20 +174,12 @@ static int write_page(void *buf, sector_t offset, int sync)
 
 void release_swap_writer(void)
 {
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
 }
 
 int hib_bio_prepare_write(void)
 {
 	int result, result2;
 
-	handle.cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
-
-	if (!handle.cur)
-		return -ENOMEM;
-
 	result = hib_prepare_buffer();
 	if (result) {
 		release_swap_writer();
@@ -232,8 +191,6 @@ int hib_bio_prepare_write(void)
 	result = hib_extents_store(&sector_extents);
 	result2 = hib_flush_write_buffer();
 
-	handle.k = 0;
-
 	if (result || result2)
 		release_swap_writer();
 
@@ -244,8 +201,6 @@ int swap_write_page(void *buf, int sync)
 {
 	sector_t offset;
 
-	if (!handle.cur)
-		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
 	return write_page(buf, offset, sync);
 }
@@ -263,19 +218,12 @@ int flush_swap_writer(void)
 
 void release_swap_reader(void)
 {
-	if (handle.cur)
-		free_page((unsigned long)handle.cur);
-	handle.cur = NULL;
 }
 
 int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 {
 	int error;
 
-	handle.cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
-	if (!handle.cur)
-		return -ENOMEM;
-
 	error = hib_prepare_buffer();
 	if (error) {
 		release_swap_reader();
@@ -290,8 +238,6 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 		return error;
 	}
 
-	handle.k = 0;
-
 	error = hib_extents_load(&sector_extents, 1);
 
 	if (error) {
@@ -306,8 +252,6 @@ int swap_read_page(void *buf, int sync)
 {
 	sector_t offset;
 
-	if (!handle.cur)
-		return -EINVAL;
 	offset = hib_extent_next(&sector_extents);
 	if (!offset)
 		return -EFAULT;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 22/23] Hibernation: Remove now-empty routines.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (45 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 22/23] Hibernation: Remove now-empty routines Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` [PATCH 23/23] Hibernate: Implement readahead when resuming Nigel Cunningham
                   ` (6 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

release_swap_writer and release_swap_reader are now empty functions.
Remove them and clean up callers (including swap_reader_finish, which
just called release_swap_reader).

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   36 ++++--------------------------------
 kernel/power/block_io.h |    2 --
 kernel/power/swap.c     |    9 ---------
 3 files changed, 4 insertions(+), 43 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index f452650..fc2e05d 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -172,28 +172,19 @@ static int write_page(void *buf, sector_t offset, int sync)
 	return hib_bio_write_page(offset, src, sync);
 }
 
-void release_swap_writer(void)
-{
-}
-
 int hib_bio_prepare_write(void)
 {
 	int result, result2;
 
 	result = hib_prepare_buffer();
-	if (result) {
-		release_swap_writer();
+	if (result)
 		return result;
-	}
 
 	first_sector = hib_extent_current(&sector_extents);
 
 	result = hib_extents_store(&sector_extents);
 	result2 = hib_flush_write_buffer();
 
-	if (result || result2)
-		release_swap_writer();
-
 	return result ? result : result2;
 }
 
@@ -211,38 +202,19 @@ int flush_swap_writer(void)
 	return 0;
 }
 
-/**
- *	The following functions allow us to read data using a swap map
- *	in a file-alike way
- */
-
-void release_swap_reader(void)
-{
-}
-
 int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 {
 	int error;
 
 	error = hib_prepare_buffer();
-	if (error) {
-		release_swap_reader();
+	if (error)
 		return error;
-	}
 
 	/* Bootstrap reading the extents */
 	error = hib_bio_read_page(first_page, hib_ppio_buffer, 1);
-	if (error) {
-		release_swap_reader();
-		hib_free_buffer();
-		return error;
-	}
 
-	error = hib_extents_load(&sector_extents, 1);
-
-	if (error) {
-		release_swap_reader();
-	}
+	if (!error)
+		error = hib_extents_load(&sector_extents, 1);
 
 	hib_free_buffer();
 	return error;
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
index 1482060..228fe58 100644
--- a/kernel/power/block_io.h
+++ b/kernel/power/block_io.h
@@ -14,12 +14,10 @@ void hib_wait_on_bio_chain(void);
 unsigned int hib_bio_overhead(unsigned int nr_pages);
 sector_t hib_get_first_sector(void);
 extern struct hib_extent_state sector_extents;
-void release_swap_writer(void);
 int hib_bio_prepare_write(void);
 int flush_swap_writer(void);
 int swap_write_page(void *buf, int sync);
 int get_swap_reader(unsigned int *flags_p, sector_t first_page);
-void release_swap_reader(void);
 int swap_read_page(void *buf, int sync);
 int hib_flush_write_buffer(void);
 
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 0a9715b..0e94484 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -216,7 +216,6 @@ static int swap_writer_finish(unsigned int flags, int error)
 
 	if (error)
 		free_all_swap_pages(root_swap);
-	release_swap_writer();
 	swsusp_close(FMODE_WRITE);
 
 	return error;
@@ -315,13 +314,6 @@ out_finish:
 	return error;
 }
 
-static int swap_reader_finish(void)
-{
-	release_swap_reader();
-
-	return 0;
-}
-
 /**
  *	load_image - load the image using the swap map handle
  *	@handle and the snapshot handle @snapshot
@@ -408,7 +400,6 @@ int swsusp_read(unsigned int *flags_p)
 		error = swap_read_page(header, 1);
 	if (!error)
 		error = load_image(&snapshot, header->pages - 1, *flags_p);
-	swap_reader_finish();
 end:
 	compress_image_cleanup();
 	if (!error)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 22/23] Hibernation: Remove now-empty routines.
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (44 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (7 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

release_swap_writer and release_swap_reader are now empty functions.
Remove them and clean up callers (including swap_reader_finish, which
just called release_swap_reader).

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   36 ++++--------------------------------
 kernel/power/block_io.h |    2 --
 kernel/power/swap.c     |    9 ---------
 3 files changed, 4 insertions(+), 43 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index f452650..fc2e05d 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -172,28 +172,19 @@ static int write_page(void *buf, sector_t offset, int sync)
 	return hib_bio_write_page(offset, src, sync);
 }
 
-void release_swap_writer(void)
-{
-}
-
 int hib_bio_prepare_write(void)
 {
 	int result, result2;
 
 	result = hib_prepare_buffer();
-	if (result) {
-		release_swap_writer();
+	if (result)
 		return result;
-	}
 
 	first_sector = hib_extent_current(&sector_extents);
 
 	result = hib_extents_store(&sector_extents);
 	result2 = hib_flush_write_buffer();
 
-	if (result || result2)
-		release_swap_writer();
-
 	return result ? result : result2;
 }
 
@@ -211,38 +202,19 @@ int flush_swap_writer(void)
 	return 0;
 }
 
-/**
- *	The following functions allow us to read data using a swap map
- *	in a file-alike way
- */
-
-void release_swap_reader(void)
-{
-}
-
 int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 {
 	int error;
 
 	error = hib_prepare_buffer();
-	if (error) {
-		release_swap_reader();
+	if (error)
 		return error;
-	}
 
 	/* Bootstrap reading the extents */
 	error = hib_bio_read_page(first_page, hib_ppio_buffer, 1);
-	if (error) {
-		release_swap_reader();
-		hib_free_buffer();
-		return error;
-	}
 
-	error = hib_extents_load(&sector_extents, 1);
-
-	if (error) {
-		release_swap_reader();
-	}
+	if (!error)
+		error = hib_extents_load(&sector_extents, 1);
 
 	hib_free_buffer();
 	return error;
diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h
index 1482060..228fe58 100644
--- a/kernel/power/block_io.h
+++ b/kernel/power/block_io.h
@@ -14,12 +14,10 @@ void hib_wait_on_bio_chain(void);
 unsigned int hib_bio_overhead(unsigned int nr_pages);
 sector_t hib_get_first_sector(void);
 extern struct hib_extent_state sector_extents;
-void release_swap_writer(void);
 int hib_bio_prepare_write(void);
 int flush_swap_writer(void);
 int swap_write_page(void *buf, int sync);
 int get_swap_reader(unsigned int *flags_p, sector_t first_page);
-void release_swap_reader(void);
 int swap_read_page(void *buf, int sync);
 int hib_flush_write_buffer(void);
 
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 0a9715b..0e94484 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -216,7 +216,6 @@ static int swap_writer_finish(unsigned int flags, int error)
 
 	if (error)
 		free_all_swap_pages(root_swap);
-	release_swap_writer();
 	swsusp_close(FMODE_WRITE);
 
 	return error;
@@ -315,13 +314,6 @@ out_finish:
 	return error;
 }
 
-static int swap_reader_finish(void)
-{
-	release_swap_reader();
-
-	return 0;
-}
-
 /**
  *	load_image - load the image using the swap map handle
  *	@handle and the snapshot handle @snapshot
@@ -408,7 +400,6 @@ int swsusp_read(unsigned int *flags_p)
 		error = swap_read_page(header, 1);
 	if (!error)
 		error = load_image(&snapshot, header->pages - 1, *flags_p);
-	swap_reader_finish();
 end:
 	compress_image_cleanup();
 	if (!error)
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 23/23] Hibernate: Implement readahead when resuming
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (47 preceding siblings ...)
  2010-09-27  5:43 ` [PATCH 23/23] Hibernate: Implement readahead when resuming Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  6:59   ` Andrey Rahmatullin
                   ` (4 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add support for submitting reads before they're needed. This greatly
improves the speed of resuming:

From

PM: Image read at 66 MB/s.

to

PM: Image read at 229 MB/s.

...and removes the need for the sync_read flag.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   89 ++++++++++++++++++++++++++++++++++++++++++++---
 kernel/power/power.h    |    4 --
 kernel/power/snapshot.c |    5 ---
 kernel/power/swap.c     |    2 -
 4 files changed, 84 insertions(+), 16 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index fc2e05d..70ac2c5 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -24,6 +24,9 @@ void hib_free_buffer(void);
 static atomic_t hib_io_in_progress;
 static DECLARE_WAIT_QUEUE_HEAD(num_in_progress_wait);
 
+static int more_readahead = 1, readahead_list_size;
+static struct page *readahead_list_head, *readahead_list_tail;
+
 /**
  * hib_end_bio - bio completion function.
  * @bio: bio that has completed.
@@ -67,13 +70,14 @@ static void hib_end_bio(struct bio *bio, int err)
  *	@off	physical offset of page.
  *	@page:	page we're reading or writing.
  *	@sync:	whether the i/o should be done synchronously
+ *	@ra:	whether the page is readahead
  *
  *	Straight from the textbook - allocate and initialize the bio.
  *	If we're reading, make sure the page is marked as dirty.
  *	Then submit it and, if @sync, wait.
  */
 static int submit(int rw, struct block_device *bdev, sector_t sector,
-		struct page *page, int sync)
+		struct page *page, int sync, int ra)
 {
 	const int bio_rw = rw | REQ_SYNC | REQ_UNPLUG;
 	struct bio *bio;
@@ -95,6 +99,18 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	bio_get(bio);
 	atomic_inc(&hib_io_in_progress);
 
+	page->private = 0;
+
+	if (ra) {
+		if (readahead_list_head)
+			readahead_list_tail->private = (unsigned long) page;
+		else
+			readahead_list_head = page;
+
+		readahead_list_tail = page;
+		readahead_list_size++;
+	}
+
 	if (sync) {
 		submit_bio(bio_rw, bio);
 		wait_on_page_locked(page);
@@ -112,18 +128,25 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 int hib_bio_read_page(pgoff_t page_off, void *addr, int sync)
 {
 	return submit(READ, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
-			virt_to_page(addr), sync);
+			virt_to_page(addr), sync, 0);
 }
 
 int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 {
 	return submit(WRITE, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
-			virt_to_page(addr), sync);
+			virt_to_page(addr), sync, 0);
 }
 
 void hib_wait_on_bio_chain(void)
 {
 	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
+
+	while (readahead_list_head) {
+		struct page *next = (struct page *) readahead_list_head->private;
+		__free_page(readahead_list_head);
+		readahead_list_head = next;
+		readahead_list_size--;
+	}
 }
 
 static sector_t first_sector;
@@ -220,14 +243,70 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 	return error;
 }
 
-int swap_read_page(void *buf, int sync)
+int start_one_readahead(void)
 {
 	sector_t offset;
+	struct page *ra_page;
+	int result = 0;
+
+	if (!more_readahead)
+		return 0;
+
+	ra_page = alloc_pages(GFP_NOIO, 0);
+
+	/* No memory for readahead? */
+	if (!ra_page)
+		return 0;
 
 	offset = hib_extent_next(&sector_extents);
 	if (!offset)
+		more_readahead = 0;
+	else
+		result = submit(READ, hib_resume_bdev,
+				offset * (PAGE_SIZE >> 9),
+				ra_page, 0, 1);
+
+	if (result)
+		__free_page(ra_page);
+
+	return result;
+}
+
+int start_more_readahead(void)
+{
+	int ret = 0;
+
+	while (!ret && readahead_list_size < 1000 && more_readahead)
+		ret = start_one_readahead();
+
+	return ret;
+}
+
+int swap_read_page(void *buf, int sync)
+{
+	char *ra;
+	struct page *old;
+	int err = start_more_readahead();
+
+	if (err)
+		return err;
+
+	if (!readahead_list_head)
 		return -EFAULT;
-	return hib_bio_read_page(offset, buf, sync);
+
+	wait_on_page_locked(readahead_list_head);
+
+	ra = kmap(readahead_list_head);
+	memcpy(buf, ra, PAGE_SIZE);
+	kunmap(readahead_list_head);
+
+	old = readahead_list_head;
+	readahead_list_head = (struct page *) old->private;
+	__free_page(old);
+
+	readahead_list_size--;
+
+	return 0;
 }
 
 /* Part Page I/O functions */
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 9525b9c..aecb8ec 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -111,10 +111,6 @@ struct snapshot_handle {
 	void		*buffer;	/* address of the block to read from
 					 * or write to
 					 */
-	int		sync_read;	/* Set to one to notify the caller of
-					 * snapshot_write_next() that it may
-					 * need to call wait_on_bio_chain()
-					 */
 };
 
 /* This macro returns the address from/to which the caller of
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index ac7eb10..1f875a0 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -2187,8 +2187,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
 	if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages)
 		return 0;
 
-	handle->sync_read = 1;
-
 	if (!handle->cur) {
 		if (!buffer)
 			/* This makes the buffer be freed by swsusp_free() */
@@ -2221,7 +2219,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
 			memory_bm_position_reset(&orig_bm);
 			restore_pblist = NULL;
 			handle->buffer = get_buffer(&orig_bm, &ca);
-			handle->sync_read = 0;
 			if (IS_ERR(handle->buffer))
 				return PTR_ERR(handle->buffer);
 		}
@@ -2230,8 +2227,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
 		handle->buffer = get_buffer(&orig_bm, &ca);
 		if (IS_ERR(handle->buffer))
 			return PTR_ERR(handle->buffer);
-		if (handle->buffer != buffer)
-			handle->sync_read = 0;
 	}
 	handle->cur++;
 	return PAGE_SIZE;
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 0e94484..fb3a21f 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -344,8 +344,6 @@ static int load_image(struct snapshot_handle *snapshot,
 		error = compress_read(data_of(*snapshot), flags);
 		if (error)
 			break;
-		if (snapshot->sync_read)
-			hib_wait_on_bio_chain();
 		if (!(nr_pages % m))
 			printk("\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [PATCH 23/23] Hibernate: Implement readahead when resuming
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (46 preceding siblings ...)
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27  5:43 ` Nigel Cunningham
                   ` (5 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Add support for submitting reads before they're needed. This greatly
improves the speed of resuming:

From

PM: Image read at 66 MB/s.

to

PM: Image read at 229 MB/s.

...and removes the need for the sync_read flag.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/block_io.c |   89 ++++++++++++++++++++++++++++++++++++++++++++---
 kernel/power/power.h    |    4 --
 kernel/power/snapshot.c |    5 ---
 kernel/power/swap.c     |    2 -
 4 files changed, 84 insertions(+), 16 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index fc2e05d..70ac2c5 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -24,6 +24,9 @@ void hib_free_buffer(void);
 static atomic_t hib_io_in_progress;
 static DECLARE_WAIT_QUEUE_HEAD(num_in_progress_wait);
 
+static int more_readahead = 1, readahead_list_size;
+static struct page *readahead_list_head, *readahead_list_tail;
+
 /**
  * hib_end_bio - bio completion function.
  * @bio: bio that has completed.
@@ -67,13 +70,14 @@ static void hib_end_bio(struct bio *bio, int err)
  *	@off	physical offset of page.
  *	@page:	page we're reading or writing.
  *	@sync:	whether the i/o should be done synchronously
+ *	@ra:	whether the page is readahead
  *
  *	Straight from the textbook - allocate and initialize the bio.
  *	If we're reading, make sure the page is marked as dirty.
  *	Then submit it and, if @sync, wait.
  */
 static int submit(int rw, struct block_device *bdev, sector_t sector,
-		struct page *page, int sync)
+		struct page *page, int sync, int ra)
 {
 	const int bio_rw = rw | REQ_SYNC | REQ_UNPLUG;
 	struct bio *bio;
@@ -95,6 +99,18 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 	bio_get(bio);
 	atomic_inc(&hib_io_in_progress);
 
+	page->private = 0;
+
+	if (ra) {
+		if (readahead_list_head)
+			readahead_list_tail->private = (unsigned long) page;
+		else
+			readahead_list_head = page;
+
+		readahead_list_tail = page;
+		readahead_list_size++;
+	}
+
 	if (sync) {
 		submit_bio(bio_rw, bio);
 		wait_on_page_locked(page);
@@ -112,18 +128,25 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
 int hib_bio_read_page(pgoff_t page_off, void *addr, int sync)
 {
 	return submit(READ, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
-			virt_to_page(addr), sync);
+			virt_to_page(addr), sync, 0);
 }
 
 int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
 {
 	return submit(WRITE, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
-			virt_to_page(addr), sync);
+			virt_to_page(addr), sync, 0);
 }
 
 void hib_wait_on_bio_chain(void)
 {
 	wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
+
+	while (readahead_list_head) {
+		struct page *next = (struct page *) readahead_list_head->private;
+		__free_page(readahead_list_head);
+		readahead_list_head = next;
+		readahead_list_size--;
+	}
 }
 
 static sector_t first_sector;
@@ -220,14 +243,70 @@ int get_swap_reader(unsigned int *flags_p, sector_t first_page)
 	return error;
 }
 
-int swap_read_page(void *buf, int sync)
+int start_one_readahead(void)
 {
 	sector_t offset;
+	struct page *ra_page;
+	int result = 0;
+
+	if (!more_readahead)
+		return 0;
+
+	ra_page = alloc_pages(GFP_NOIO, 0);
+
+	/* No memory for readahead? */
+	if (!ra_page)
+		return 0;
 
 	offset = hib_extent_next(&sector_extents);
 	if (!offset)
+		more_readahead = 0;
+	else
+		result = submit(READ, hib_resume_bdev,
+				offset * (PAGE_SIZE >> 9),
+				ra_page, 0, 1);
+
+	if (result)
+		__free_page(ra_page);
+
+	return result;
+}
+
+int start_more_readahead(void)
+{
+	int ret = 0;
+
+	while (!ret && readahead_list_size < 1000 && more_readahead)
+		ret = start_one_readahead();
+
+	return ret;
+}
+
+int swap_read_page(void *buf, int sync)
+{
+	char *ra;
+	struct page *old;
+	int err = start_more_readahead();
+
+	if (err)
+		return err;
+
+	if (!readahead_list_head)
 		return -EFAULT;
-	return hib_bio_read_page(offset, buf, sync);
+
+	wait_on_page_locked(readahead_list_head);
+
+	ra = kmap(readahead_list_head);
+	memcpy(buf, ra, PAGE_SIZE);
+	kunmap(readahead_list_head);
+
+	old = readahead_list_head;
+	readahead_list_head = (struct page *) old->private;
+	__free_page(old);
+
+	readahead_list_size--;
+
+	return 0;
 }
 
 /* Part Page I/O functions */
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 9525b9c..aecb8ec 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -111,10 +111,6 @@ struct snapshot_handle {
 	void		*buffer;	/* address of the block to read from
 					 * or write to
 					 */
-	int		sync_read;	/* Set to one to notify the caller of
-					 * snapshot_write_next() that it may
-					 * need to call wait_on_bio_chain()
-					 */
 };
 
 /* This macro returns the address from/to which the caller of
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index ac7eb10..1f875a0 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -2187,8 +2187,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
 	if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages)
 		return 0;
 
-	handle->sync_read = 1;
-
 	if (!handle->cur) {
 		if (!buffer)
 			/* This makes the buffer be freed by swsusp_free() */
@@ -2221,7 +2219,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
 			memory_bm_position_reset(&orig_bm);
 			restore_pblist = NULL;
 			handle->buffer = get_buffer(&orig_bm, &ca);
-			handle->sync_read = 0;
 			if (IS_ERR(handle->buffer))
 				return PTR_ERR(handle->buffer);
 		}
@@ -2230,8 +2227,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
 		handle->buffer = get_buffer(&orig_bm, &ca);
 		if (IS_ERR(handle->buffer))
 			return PTR_ERR(handle->buffer);
-		if (handle->buffer != buffer)
-			handle->sync_read = 0;
 	}
 	handle->cur++;
 	return PAGE_SIZE;
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 0e94484..fb3a21f 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -344,8 +344,6 @@ static int load_image(struct snapshot_handle *snapshot,
 		error = compress_read(data_of(*snapshot), flags);
 		if (error)
 			break;
-		if (snapshot->sync_read)
-			hib_wait_on_bio_chain();
 		if (!(nr_pages % m))
 			printk("\b\b\b\b%3d%%", nr_pages / m);
 		nr_pages++;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
@ 2010-09-27  6:59   ` Andrey Rahmatullin
  2010-09-27  5:43 ` Nigel Cunningham
                     ` (52 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Andrey Rahmatullin @ 2010-09-27  6:59 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

[-- Attachment #1: Type: text/plain, Size: 907 bytes --]

On Mon, Sep 27, 2010 at 03:43:35PM +1000, Nigel Cunningham wrote:
> Hi again Rafael.
> 
> As discussed, here are the patches, modified to apply against your current
> linux-next tree. A new first patch splits compression support out into its
> own file, removing the need to have two versions of the load_image and
> save_image routines, minimising the changes to the remainder of the
> patches and making things cleaner than would otherwise be the case.
> 
> On my laptop, single-threaded compression actually slows writing down from
> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
> Reading speed improves from 218MB/s to around 245MB/s. I expect that
> multithreaded writing would bring the writing (and reading) speeds back
> up. It's on my swsusp to do list :)
Can I test this patchset by just building for-rafael branch?

-- 
WBR, wRAR (ALT Linux Team)

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
@ 2010-09-27  6:59   ` Andrey Rahmatullin
  0 siblings, 0 replies; 113+ messages in thread
From: Andrey Rahmatullin @ 2010-09-27  6:59 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel


[-- Attachment #1.1: Type: text/plain, Size: 907 bytes --]

On Mon, Sep 27, 2010 at 03:43:35PM +1000, Nigel Cunningham wrote:
> Hi again Rafael.
> 
> As discussed, here are the patches, modified to apply against your current
> linux-next tree. A new first patch splits compression support out into its
> own file, removing the need to have two versions of the load_image and
> save_image routines, minimising the changes to the remainder of the
> patches and making things cleaner than would otherwise be the case.
> 
> On my laptop, single-threaded compression actually slows writing down from
> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
> Reading speed improves from 218MB/s to around 245MB/s. I expect that
> multithreaded writing would bring the writing (and reading) speeds back
> up. It's on my swsusp to do list :)
Can I test this patchset by just building for-rafael branch?

-- 
WBR, wRAR (ALT Linux Team)

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (50 preceding siblings ...)
  2010-09-27  8:00 ` Andrey Rahmatullin
@ 2010-09-27  8:00 ` Andrey Rahmatullin
  2010-09-27  8:29   ` Nigel Cunningham
  2010-09-27  8:29   ` Nigel Cunningham
  2010-10-02 16:49 ` Martin Steigerwald
  2010-10-02 16:49 ` [linux-pm] " Martin Steigerwald
  53 siblings, 2 replies; 113+ messages in thread
From: Andrey Rahmatullin @ 2010-09-27  8:00 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

[-- Attachment #1: Type: text/plain, Size: 858 bytes --]

On Mon, Sep 27, 2010 at 03:43:35PM +1000, Nigel Cunningham wrote:
> Hi again Rafael.
> 
> As discussed, here are the patches, modified to apply against your current
> linux-next tree. A new first patch splits compression support out into its
> own file, removing the need to have two versions of the load_image and
> save_image routines, minimising the changes to the remainder of the
> patches and making things cleaner than would otherwise be the case.
> 
> On my laptop, single-threaded compression actually slows writing down from
> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
> Reading speed improves from 218MB/s to around 245MB/s. I expect that
> multithreaded writing would bring the writing (and reading) speeds back
> up. It's on my swsusp to do list :)
Works here.

-- 
WBR, wRAR (ALT Linux Team)

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (49 preceding siblings ...)
  2010-09-27  6:59   ` Andrey Rahmatullin
@ 2010-09-27  8:00 ` Andrey Rahmatullin
  2010-09-27  8:00 ` Andrey Rahmatullin
                   ` (2 subsequent siblings)
  53 siblings, 0 replies; 113+ messages in thread
From: Andrey Rahmatullin @ 2010-09-27  8:00 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel


[-- Attachment #1.1: Type: text/plain, Size: 858 bytes --]

On Mon, Sep 27, 2010 at 03:43:35PM +1000, Nigel Cunningham wrote:
> Hi again Rafael.
> 
> As discussed, here are the patches, modified to apply against your current
> linux-next tree. A new first patch splits compression support out into its
> own file, removing the need to have two versions of the load_image and
> save_image routines, minimising the changes to the remainder of the
> patches and making things cleaner than would otherwise be the case.
> 
> On my laptop, single-threaded compression actually slows writing down from
> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
> Reading speed improves from 218MB/s to around 245MB/s. I expect that
> multithreaded writing would bring the writing (and reading) speeds back
> up. It's on my swsusp to do list :)
Works here.

-- 
WBR, wRAR (ALT Linux Team)

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  6:59   ` Andrey Rahmatullin
  (?)
@ 2010-09-27  8:28   ` Nigel Cunningham
  -1 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  8:28 UTC (permalink / raw)
  To: Andrey Rahmatullin; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi.

On 27/09/10 16:59, Andrey Rahmatullin wrote:
> On Mon, Sep 27, 2010 at 03:43:35PM +1000, Nigel Cunningham wrote:
>> Hi again Rafael.
>>
>> As discussed, here are the patches, modified to apply against your current
>> linux-next tree. A new first patch splits compression support out into its
>> own file, removing the need to have two versions of the load_image and
>> save_image routines, minimising the changes to the remainder of the
>> patches and making things cleaner than would otherwise be the case.
>>
>> On my laptop, single-threaded compression actually slows writing down from
>> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
>> Reading speed improves from 218MB/s to around 245MB/s. I expect that
>> multithreaded writing would bring the writing (and reading) speeds back
>> up. It's on my swsusp to do list :)
> Can I test this patchset by just building for-rafael branch?

I don't have it available on git at the moment, but since you're 
interested, I'll address that...

Okay. There's a new suspend-next branch in the tuxonice-head tree that 
has what you're after.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  6:59   ` Andrey Rahmatullin
  (?)
  (?)
@ 2010-09-27  8:28   ` Nigel Cunningham
  -1 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  8:28 UTC (permalink / raw)
  To: Andrey Rahmatullin; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 27/09/10 16:59, Andrey Rahmatullin wrote:
> On Mon, Sep 27, 2010 at 03:43:35PM +1000, Nigel Cunningham wrote:
>> Hi again Rafael.
>>
>> As discussed, here are the patches, modified to apply against your current
>> linux-next tree. A new first patch splits compression support out into its
>> own file, removing the need to have two versions of the load_image and
>> save_image routines, minimising the changes to the remainder of the
>> patches and making things cleaner than would otherwise be the case.
>>
>> On my laptop, single-threaded compression actually slows writing down from
>> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
>> Reading speed improves from 218MB/s to around 245MB/s. I expect that
>> multithreaded writing would bring the writing (and reading) speeds back
>> up. It's on my swsusp to do list :)
> Can I test this patchset by just building for-rafael branch?

I don't have it available on git at the moment, but since you're 
interested, I'll address that...

Okay. There's a new suspend-next branch in the tuxonice-head tree that 
has what you're after.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  8:00 ` Andrey Rahmatullin
  2010-09-27  8:29   ` Nigel Cunningham
@ 2010-09-27  8:29   ` Nigel Cunningham
  2010-09-27  9:38     ` Andrey Rahmatullin
                       ` (3 more replies)
  1 sibling, 4 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  8:29 UTC (permalink / raw)
  To: Andrey Rahmatullin; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi.

On 27/09/10 18:00, Andrey Rahmatullin wrote:
> On Mon, Sep 27, 2010 at 03:43:35PM +1000, Nigel Cunningham wrote:
>> Hi again Rafael.
>>
>> As discussed, here are the patches, modified to apply against your current
>> linux-next tree. A new first patch splits compression support out into its
>> own file, removing the need to have two versions of the load_image and
>> save_image routines, minimising the changes to the remainder of the
>> patches and making things cleaner than would otherwise be the case.
>>
>> On my laptop, single-threaded compression actually slows writing down from
>> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
>> Reading speed improves from 218MB/s to around 245MB/s. I expect that
>> multithreaded writing would bring the writing (and reading) speeds back
>> up. It's on my swsusp to do list :)
> Works here.

Ah. You're too fast for me :)

What sort of speeds are you seeing?

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  8:00 ` Andrey Rahmatullin
@ 2010-09-27  8:29   ` Nigel Cunningham
  2010-09-27  8:29   ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  8:29 UTC (permalink / raw)
  To: Andrey Rahmatullin; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 27/09/10 18:00, Andrey Rahmatullin wrote:
> On Mon, Sep 27, 2010 at 03:43:35PM +1000, Nigel Cunningham wrote:
>> Hi again Rafael.
>>
>> As discussed, here are the patches, modified to apply against your current
>> linux-next tree. A new first patch splits compression support out into its
>> own file, removing the need to have two versions of the load_image and
>> save_image routines, minimising the changes to the remainder of the
>> patches and making things cleaner than would otherwise be the case.
>>
>> On my laptop, single-threaded compression actually slows writing down from
>> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
>> Reading speed improves from 218MB/s to around 245MB/s. I expect that
>> multithreaded writing would bring the writing (and reading) speeds back
>> up. It's on my swsusp to do list :)
> Works here.

Ah. You're too fast for me :)

What sort of speeds are you seeing?

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  8:29   ` Nigel Cunningham
@ 2010-09-27  9:38     ` Andrey Rahmatullin
  2010-09-27  9:57       ` Nigel Cunningham
  2010-09-27  9:57       ` Nigel Cunningham
  2010-09-27  9:38     ` Andrey Rahmatullin
                       ` (2 subsequent siblings)
  3 siblings, 2 replies; 113+ messages in thread
From: Andrey Rahmatullin @ 2010-09-27  9:38 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

[-- Attachment #1: Type: text/plain, Size: 1054 bytes --]

On Mon, Sep 27, 2010 at 06:29:35PM +1000, Nigel Cunningham wrote:
> >> As discussed, here are the patches, modified to apply against your current
> >> linux-next tree. A new first patch splits compression support out into its
> >> own file, removing the need to have two versions of the load_image and
> >> save_image routines, minimising the changes to the remainder of the
> >> patches and making things cleaner than would otherwise be the case.
> >>
> >> On my laptop, single-threaded compression actually slows writing down from
> >> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
> >> Reading speed improves from 218MB/s to around 245MB/s. I expect that
> >> multithreaded writing would bring the writing (and reading) speeds back
> >> up. It's on my swsusp to do list :)
> > Works here.
> 
> Ah. You're too fast for me :)
> 
> What sort of speeds are you seeing?
Well, I don't see any 'PM: Image read at' etc in the kernel logs after
resuming (in for-rafael tree).

-- 
WBR, wRAR (ALT Linux Team)

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  8:29   ` Nigel Cunningham
  2010-09-27  9:38     ` Andrey Rahmatullin
@ 2010-09-27  9:38     ` Andrey Rahmatullin
  2010-09-27 11:16     ` Andrey Rahmatullin
  2010-09-27 11:16     ` Andrey Rahmatullin
  3 siblings, 0 replies; 113+ messages in thread
From: Andrey Rahmatullin @ 2010-09-27  9:38 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel


[-- Attachment #1.1: Type: text/plain, Size: 1054 bytes --]

On Mon, Sep 27, 2010 at 06:29:35PM +1000, Nigel Cunningham wrote:
> >> As discussed, here are the patches, modified to apply against your current
> >> linux-next tree. A new first patch splits compression support out into its
> >> own file, removing the need to have two versions of the load_image and
> >> save_image routines, minimising the changes to the remainder of the
> >> patches and making things cleaner than would otherwise be the case.
> >>
> >> On my laptop, single-threaded compression actually slows writing down from
> >> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
> >> Reading speed improves from 218MB/s to around 245MB/s. I expect that
> >> multithreaded writing would bring the writing (and reading) speeds back
> >> up. It's on my swsusp to do list :)
> > Works here.
> 
> Ah. You're too fast for me :)
> 
> What sort of speeds are you seeing?
Well, I don't see any 'PM: Image read at' etc in the kernel logs after
resuming (in for-rafael tree).

-- 
WBR, wRAR (ALT Linux Team)

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  9:38     ` Andrey Rahmatullin
@ 2010-09-27  9:57       ` Nigel Cunningham
  2010-09-27  9:57       ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  9:57 UTC (permalink / raw)
  To: Andrey Rahmatullin; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi.

On 27/09/10 19:38, Andrey Rahmatullin wrote:
> On Mon, Sep 27, 2010 at 06:29:35PM +1000, Nigel Cunningham wrote:
>>>> As discussed, here are the patches, modified to apply against your current
>>>> linux-next tree. A new first patch splits compression support out into its
>>>> own file, removing the need to have two versions of the load_image and
>>>> save_image routines, minimising the changes to the remainder of the
>>>> patches and making things cleaner than would otherwise be the case.
>>>>
>>>> On my laptop, single-threaded compression actually slows writing down from
>>>> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
>>>> Reading speed improves from 218MB/s to around 245MB/s. I expect that
>>>> multithreaded writing would bring the writing (and reading) speeds back
>>>> up. It's on my swsusp to do list :)
>>> Works here.
>>
>> Ah. You're too fast for me :)
>>
>> What sort of speeds are you seeing?
> Well, I don't see any 'PM: Image read at' etc in the kernel logs after
> resuming (in for-rafael tree).

You need CONFIG_PM_DEBUG enabled for that. Perhaps I should remove that 
requirement.

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  9:38     ` Andrey Rahmatullin
  2010-09-27  9:57       ` Nigel Cunningham
@ 2010-09-27  9:57       ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  9:57 UTC (permalink / raw)
  To: Andrey Rahmatullin; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 27/09/10 19:38, Andrey Rahmatullin wrote:
> On Mon, Sep 27, 2010 at 06:29:35PM +1000, Nigel Cunningham wrote:
>>>> As discussed, here are the patches, modified to apply against your current
>>>> linux-next tree. A new first patch splits compression support out into its
>>>> own file, removing the need to have two versions of the load_image and
>>>> save_image routines, minimising the changes to the remainder of the
>>>> patches and making things cleaner than would otherwise be the case.
>>>>
>>>> On my laptop, single-threaded compression actually slows writing down from
>>>> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
>>>> Reading speed improves from 218MB/s to around 245MB/s. I expect that
>>>> multithreaded writing would bring the writing (and reading) speeds back
>>>> up. It's on my swsusp to do list :)
>>> Works here.
>>
>> Ah. You're too fast for me :)
>>
>> What sort of speeds are you seeing?
> Well, I don't see any 'PM: Image read at' etc in the kernel logs after
> resuming (in for-rafael tree).

You need CONFIG_PM_DEBUG enabled for that. Perhaps I should remove that 
requirement.

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  8:29   ` Nigel Cunningham
                       ` (2 preceding siblings ...)
  2010-09-27 11:16     ` Andrey Rahmatullin
@ 2010-09-27 11:16     ` Andrey Rahmatullin
  2010-09-27 11:39       ` Nigel Cunningham
  2010-09-27 11:39       ` Nigel Cunningham
  3 siblings, 2 replies; 113+ messages in thread
From: Andrey Rahmatullin @ 2010-09-27 11:16 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

[-- Attachment #1: Type: text/plain, Size: 761 bytes --]

On Mon, Sep 27, 2010 at 06:29:35PM +1000, Nigel Cunningham wrote:
> >> On my laptop, single-threaded compression actually slows writing down from
> >> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
> >> Reading speed improves from 218MB/s to around 245MB/s. I expect that
> >> multithreaded writing would bring the writing (and reading) speeds back
> >> up. It's on my swsusp to do list :)
> > Works here.
> What sort of speeds are you seeing?
[  343.549378] PM: Image written at 107 MB/s.
[  343.549379] PM: Image read at 205 MB/s.
Latest ToI (on .35; with the lzo compressor; no clue about
multithreadedness, though there are 4 CPUs here): I/O speed: Write 166
MB/s, Read 192 MB/s.

-- 
WBR, wRAR (ALT Linux Team)

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  8:29   ` Nigel Cunningham
  2010-09-27  9:38     ` Andrey Rahmatullin
  2010-09-27  9:38     ` Andrey Rahmatullin
@ 2010-09-27 11:16     ` Andrey Rahmatullin
  2010-09-27 11:16     ` Andrey Rahmatullin
  3 siblings, 0 replies; 113+ messages in thread
From: Andrey Rahmatullin @ 2010-09-27 11:16 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel


[-- Attachment #1.1: Type: text/plain, Size: 761 bytes --]

On Mon, Sep 27, 2010 at 06:29:35PM +1000, Nigel Cunningham wrote:
> >> On my laptop, single-threaded compression actually slows writing down from
> >> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
> >> Reading speed improves from 218MB/s to around 245MB/s. I expect that
> >> multithreaded writing would bring the writing (and reading) speeds back
> >> up. It's on my swsusp to do list :)
> > Works here.
> What sort of speeds are you seeing?
[  343.549378] PM: Image written at 107 MB/s.
[  343.549379] PM: Image read at 205 MB/s.
Latest ToI (on .35; with the lzo compressor; no clue about
multithreadedness, though there are 4 CPUs here): I/O speed: Write 166
MB/s, Read 192 MB/s.

-- 
WBR, wRAR (ALT Linux Team)

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27 11:16     ` Andrey Rahmatullin
@ 2010-09-27 11:39       ` Nigel Cunningham
  2010-09-27 11:39       ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27 11:39 UTC (permalink / raw)
  To: Andrey Rahmatullin; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi.

On 27/09/10 21:16, Andrey Rahmatullin wrote:
> On Mon, Sep 27, 2010 at 06:29:35PM +1000, Nigel Cunningham wrote:
>>>> On my laptop, single-threaded compression actually slows writing down from
>>>> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
>>>> Reading speed improves from 218MB/s to around 245MB/s. I expect that
>>>> multithreaded writing would bring the writing (and reading) speeds back
>>>> up. It's on my swsusp to do list :)
>>> Works here.
>> What sort of speeds are you seeing?
> [  343.549378] PM: Image written at 107 MB/s.
> [  343.549379] PM: Image read at 205 MB/s.
> Latest ToI (on .35; with the lzo compressor; no clue about
> multithreadedness, though there are 4 CPUs here): I/O speed: Write 166
> MB/s, Read 192 MB/s.

Cool. Thanks!

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27 11:16     ` Andrey Rahmatullin
  2010-09-27 11:39       ` Nigel Cunningham
@ 2010-09-27 11:39       ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27 11:39 UTC (permalink / raw)
  To: Andrey Rahmatullin; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 27/09/10 21:16, Andrey Rahmatullin wrote:
> On Mon, Sep 27, 2010 at 06:29:35PM +1000, Nigel Cunningham wrote:
>>>> On my laptop, single-threaded compression actually slows writing down from
>>>> 175MB/s to around 100-120MB/s (depending on how well the image compresses).
>>>> Reading speed improves from 218MB/s to around 245MB/s. I expect that
>>>> multithreaded writing would bring the writing (and reading) speeds back
>>>> up. It's on my swsusp to do list :)
>>> Works here.
>> What sort of speeds are you seeing?
> [  343.549378] PM: Image written at 107 MB/s.
> [  343.549379] PM: Image read at 205 MB/s.
> Latest ToI (on .35; with the lzo compressor; no clue about
> multithreadedness, though there are 4 CPUs here): I/O speed: Write 166
> MB/s, Read 192 MB/s.

Cool. Thanks!

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27  5:43 ` [PATCH 02/23] Record & display i/o speed post resume Nigel Cunningham
  2010-09-27 20:06   ` Rafael J. Wysocki
@ 2010-09-27 20:06   ` Rafael J. Wysocki
  2010-09-27 20:26     ` Nigel Cunningham
  2010-09-27 20:26     ` Nigel Cunningham
  1 sibling, 2 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-09-27 20:06 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Record the speed at which the image is written and read, and
> display it to the user post-resume.
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
> ---
>  kernel/power/hibernate.c |   11 ++++++++++-
>  kernel/power/power.h     |    3 ++-
>  kernel/power/swap.c      |   14 +++++++++++---
>  3 files changed, 23 insertions(+), 5 deletions(-)
> 
> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index 6c9c9dc..0cd1f05 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
>   *	@msg -		introductory message to print
>   */
>  
> -void swsusp_show_speed(struct timeval *start, struct timeval *stop,
> +int swsusp_show_speed(struct timeval *start, struct timeval *stop,
>  			unsigned nr_pages, char *msg)
>  {
>  	s64 elapsed_centisecs64;
> @@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>  			msg, k,
>  			centisecs / 100, centisecs % 100,
>  			kps / 1000, (kps % 1000) / 10);
> +	return kps / 1000;
>  }
>  
>  /**
> @@ -648,6 +649,14 @@ int hibernate(void)
>  			power_down();
>  	} else {
>  		pr_debug("PM: Image restored successfully.\n");
> +		if (write_speed)
> +			pr_debug("PM: Image written at %u MB/s.\n",
> +					(u8) write_speed);
> +		write_speed = 0;
> +		if (read_speed)
> +			pr_debug("PM: Image read at %u MB/s.\n",
> +					(u8) read_speed);
> +		read_speed = 0;
>  	}
>  
>   Thaw:
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index 03634be..22f8607 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
>  extern int hibernation_restore(int platform_mode);
>  extern int hibernation_platform_enter(void);
>  
> +extern char __nosavedata write_speed, read_speed;
>  #else /* !CONFIG_HIBERNATION */
>  
>  static inline void hibernate_image_size_init(void) {}
> @@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
>  
>  struct timeval;
>  /* kernel/power/swsusp.c */
> -extern void swsusp_show_speed(struct timeval *, struct timeval *,
> +extern int swsusp_show_speed(struct timeval *, struct timeval *,
>  				unsigned int, char *);
>  
>  #ifdef CONFIG_SUSPEND
> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
> index 3c01105..caf4db8 100644
> --- a/kernel/power/swap.c
> +++ b/kernel/power/swap.c
> @@ -45,7 +45,8 @@ struct swap_map_page {
>  };
>  
>  struct swsusp_header {
> -	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
> +	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
> +	char write_speed;
>  	sector_t image;
>  	unsigned int flags;	/* Flags to pass to the "boot" kernel */
>  	char	orig_sig[10];
> @@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
>  
>  static unsigned short root_swap = 0xffff;
>  struct block_device *hib_resume_bdev;
> +char __nosavedata write_speed, read_speed;

I really should have noticed that earlier, but I don't really like __nosavedata
being used here.  In fact, it shouldn't be used at all any more, because it's
meaningless on x86_64.

I'm not sure how to implement that without __nosavedata, but please don't
use it.  Sorry aboiut that.

Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27  5:43 ` [PATCH 02/23] Record & display i/o speed post resume Nigel Cunningham
@ 2010-09-27 20:06   ` Rafael J. Wysocki
  2010-09-27 20:06   ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-09-27 20:06 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Record the speed at which the image is written and read, and
> display it to the user post-resume.
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
> ---
>  kernel/power/hibernate.c |   11 ++++++++++-
>  kernel/power/power.h     |    3 ++-
>  kernel/power/swap.c      |   14 +++++++++++---
>  3 files changed, 23 insertions(+), 5 deletions(-)
> 
> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index 6c9c9dc..0cd1f05 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
>   *	@msg -		introductory message to print
>   */
>  
> -void swsusp_show_speed(struct timeval *start, struct timeval *stop,
> +int swsusp_show_speed(struct timeval *start, struct timeval *stop,
>  			unsigned nr_pages, char *msg)
>  {
>  	s64 elapsed_centisecs64;
> @@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>  			msg, k,
>  			centisecs / 100, centisecs % 100,
>  			kps / 1000, (kps % 1000) / 10);
> +	return kps / 1000;
>  }
>  
>  /**
> @@ -648,6 +649,14 @@ int hibernate(void)
>  			power_down();
>  	} else {
>  		pr_debug("PM: Image restored successfully.\n");
> +		if (write_speed)
> +			pr_debug("PM: Image written at %u MB/s.\n",
> +					(u8) write_speed);
> +		write_speed = 0;
> +		if (read_speed)
> +			pr_debug("PM: Image read at %u MB/s.\n",
> +					(u8) read_speed);
> +		read_speed = 0;
>  	}
>  
>   Thaw:
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index 03634be..22f8607 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
>  extern int hibernation_restore(int platform_mode);
>  extern int hibernation_platform_enter(void);
>  
> +extern char __nosavedata write_speed, read_speed;
>  #else /* !CONFIG_HIBERNATION */
>  
>  static inline void hibernate_image_size_init(void) {}
> @@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
>  
>  struct timeval;
>  /* kernel/power/swsusp.c */
> -extern void swsusp_show_speed(struct timeval *, struct timeval *,
> +extern int swsusp_show_speed(struct timeval *, struct timeval *,
>  				unsigned int, char *);
>  
>  #ifdef CONFIG_SUSPEND
> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
> index 3c01105..caf4db8 100644
> --- a/kernel/power/swap.c
> +++ b/kernel/power/swap.c
> @@ -45,7 +45,8 @@ struct swap_map_page {
>  };
>  
>  struct swsusp_header {
> -	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
> +	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
> +	char write_speed;
>  	sector_t image;
>  	unsigned int flags;	/* Flags to pass to the "boot" kernel */
>  	char	orig_sig[10];
> @@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
>  
>  static unsigned short root_swap = 0xffff;
>  struct block_device *hib_resume_bdev;
> +char __nosavedata write_speed, read_speed;

I really should have noticed that earlier, but I don't really like __nosavedata
being used here.  In fact, it shouldn't be used at all any more, because it's
meaningless on x86_64.

I'm not sure how to implement that without __nosavedata, but please don't
use it.  Sorry aboiut that.

Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27 20:06   ` Rafael J. Wysocki
@ 2010-09-27 20:26     ` Nigel Cunningham
  2010-09-27 20:49       ` Rafael J. Wysocki
  2010-09-27 20:49       ` Rafael J. Wysocki
  2010-09-27 20:26     ` Nigel Cunningham
  1 sibling, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27 20:26 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 28/09/10 06:06, Rafael J. Wysocki wrote:
> On Monday, September 27, 2010, Nigel Cunningham wrote:
>> Record the speed at which the image is written and read, and
>> display it to the user post-resume.
>>
>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>> ---
>>   kernel/power/hibernate.c |   11 ++++++++++-
>>   kernel/power/power.h     |    3 ++-
>>   kernel/power/swap.c      |   14 +++++++++++---
>>   3 files changed, 23 insertions(+), 5 deletions(-)
>>
>> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
>> index 6c9c9dc..0cd1f05 100644
>> --- a/kernel/power/hibernate.c
>> +++ b/kernel/power/hibernate.c
>> @@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
>>    *	@msg -		introductory message to print
>>    */
>>
>> -void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>> +int swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>   			unsigned nr_pages, char *msg)
>>   {
>>   	s64 elapsed_centisecs64;
>> @@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>   			msg, k,
>>   			centisecs / 100, centisecs % 100,
>>   			kps / 1000, (kps % 1000) / 10);
>> +	return kps / 1000;
>>   }
>>
>>   /**
>> @@ -648,6 +649,14 @@ int hibernate(void)
>>   			power_down();
>>   	} else {
>>   		pr_debug("PM: Image restored successfully.\n");
>> +		if (write_speed)
>> +			pr_debug("PM: Image written at %u MB/s.\n",
>> +					(u8) write_speed);
>> +		write_speed = 0;
>> +		if (read_speed)
>> +			pr_debug("PM: Image read at %u MB/s.\n",
>> +					(u8) read_speed);
>> +		read_speed = 0;
>>   	}
>>
>>    Thaw:
>> diff --git a/kernel/power/power.h b/kernel/power/power.h
>> index 03634be..22f8607 100644
>> --- a/kernel/power/power.h
>> +++ b/kernel/power/power.h
>> @@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
>>   extern int hibernation_restore(int platform_mode);
>>   extern int hibernation_platform_enter(void);
>>
>> +extern char __nosavedata write_speed, read_speed;
>>   #else /* !CONFIG_HIBERNATION */
>>
>>   static inline void hibernate_image_size_init(void) {}
>> @@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
>>
>>   struct timeval;
>>   /* kernel/power/swsusp.c */
>> -extern void swsusp_show_speed(struct timeval *, struct timeval *,
>> +extern int swsusp_show_speed(struct timeval *, struct timeval *,
>>   				unsigned int, char *);
>>
>>   #ifdef CONFIG_SUSPEND
>> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
>> index 3c01105..caf4db8 100644
>> --- a/kernel/power/swap.c
>> +++ b/kernel/power/swap.c
>> @@ -45,7 +45,8 @@ struct swap_map_page {
>>   };
>>
>>   struct swsusp_header {
>> -	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
>> +	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
>> +	char write_speed;
>>   	sector_t image;
>>   	unsigned int flags;	/* Flags to pass to the "boot" kernel */
>>   	char	orig_sig[10];
>> @@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
>>
>>   static unsigned short root_swap = 0xffff;
>>   struct block_device *hib_resume_bdev;
>> +char __nosavedata write_speed, read_speed;
>
> I really should have noticed that earlier, but I don't really like __nosavedata
> being used here.  In fact, it shouldn't be used at all any more, because it's
> meaningless on x86_64.

Really? Okay. When did that change?

> I'm not sure how to implement that without __nosavedata, but please don't
> use it.  Sorry aboiut that.

Well then, for now, let's drop that patch then. At least it's got us the 
numbers we needed to see these patches are useful. Longer term, I'll do 
what I do in TuxOnIce and allocate a page while writing the image, store 
it's location in the image header and use it the transfer information 
from the boot kernel to the resumed kernel. (Essentially the same thing, 
except without the special section).

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27 20:06   ` Rafael J. Wysocki
  2010-09-27 20:26     ` Nigel Cunningham
@ 2010-09-27 20:26     ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27 20:26 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 28/09/10 06:06, Rafael J. Wysocki wrote:
> On Monday, September 27, 2010, Nigel Cunningham wrote:
>> Record the speed at which the image is written and read, and
>> display it to the user post-resume.
>>
>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>> ---
>>   kernel/power/hibernate.c |   11 ++++++++++-
>>   kernel/power/power.h     |    3 ++-
>>   kernel/power/swap.c      |   14 +++++++++++---
>>   3 files changed, 23 insertions(+), 5 deletions(-)
>>
>> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
>> index 6c9c9dc..0cd1f05 100644
>> --- a/kernel/power/hibernate.c
>> +++ b/kernel/power/hibernate.c
>> @@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
>>    *	@msg -		introductory message to print
>>    */
>>
>> -void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>> +int swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>   			unsigned nr_pages, char *msg)
>>   {
>>   	s64 elapsed_centisecs64;
>> @@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>   			msg, k,
>>   			centisecs / 100, centisecs % 100,
>>   			kps / 1000, (kps % 1000) / 10);
>> +	return kps / 1000;
>>   }
>>
>>   /**
>> @@ -648,6 +649,14 @@ int hibernate(void)
>>   			power_down();
>>   	} else {
>>   		pr_debug("PM: Image restored successfully.\n");
>> +		if (write_speed)
>> +			pr_debug("PM: Image written at %u MB/s.\n",
>> +					(u8) write_speed);
>> +		write_speed = 0;
>> +		if (read_speed)
>> +			pr_debug("PM: Image read at %u MB/s.\n",
>> +					(u8) read_speed);
>> +		read_speed = 0;
>>   	}
>>
>>    Thaw:
>> diff --git a/kernel/power/power.h b/kernel/power/power.h
>> index 03634be..22f8607 100644
>> --- a/kernel/power/power.h
>> +++ b/kernel/power/power.h
>> @@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
>>   extern int hibernation_restore(int platform_mode);
>>   extern int hibernation_platform_enter(void);
>>
>> +extern char __nosavedata write_speed, read_speed;
>>   #else /* !CONFIG_HIBERNATION */
>>
>>   static inline void hibernate_image_size_init(void) {}
>> @@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
>>
>>   struct timeval;
>>   /* kernel/power/swsusp.c */
>> -extern void swsusp_show_speed(struct timeval *, struct timeval *,
>> +extern int swsusp_show_speed(struct timeval *, struct timeval *,
>>   				unsigned int, char *);
>>
>>   #ifdef CONFIG_SUSPEND
>> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
>> index 3c01105..caf4db8 100644
>> --- a/kernel/power/swap.c
>> +++ b/kernel/power/swap.c
>> @@ -45,7 +45,8 @@ struct swap_map_page {
>>   };
>>
>>   struct swsusp_header {
>> -	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
>> +	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
>> +	char write_speed;
>>   	sector_t image;
>>   	unsigned int flags;	/* Flags to pass to the "boot" kernel */
>>   	char	orig_sig[10];
>> @@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
>>
>>   static unsigned short root_swap = 0xffff;
>>   struct block_device *hib_resume_bdev;
>> +char __nosavedata write_speed, read_speed;
>
> I really should have noticed that earlier, but I don't really like __nosavedata
> being used here.  In fact, it shouldn't be used at all any more, because it's
> meaningless on x86_64.

Really? Okay. When did that change?

> I'm not sure how to implement that without __nosavedata, but please don't
> use it.  Sorry aboiut that.

Well then, for now, let's drop that patch then. At least it's got us the 
numbers we needed to see these patches are useful. Longer term, I'll do 
what I do in TuxOnIce and allocate a page while writing the image, store 
it's location in the image header and use it the transfer information 
from the boot kernel to the resumed kernel. (Essentially the same thing, 
except without the special section).

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-09-27 20:27   ` Rafael J. Wysocki
  2010-09-27 20:32     ` Nigel Cunningham
  2010-09-27 20:32     ` Nigel Cunningham
  2010-09-27 20:27   ` Rafael J. Wysocki
  1 sibling, 2 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-09-27 20:27 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Separate compression support out into its own file, removing in
> the process the duplication of the load_image and save_image
> functions and some #includes from swap.c that are no longer
> needed.
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>

If you're at it, I'd like to do something slightly different.  Explained below.

> ---
>  kernel/power/Makefile   |    2 +-
>  kernel/power/compress.c |  210 +++++++++++++++++++++++++++++
>  kernel/power/compress.h |   23 +++
>  kernel/power/swap.c     |  339 +++++------------------------------------------
>  kernel/power/swap.h     |   28 ++++
>  5 files changed, 296 insertions(+), 306 deletions(-)
>  create mode 100644 kernel/power/compress.c
>  create mode 100644 kernel/power/compress.h
>  create mode 100644 kernel/power/swap.h
> 
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index f9063c6..2eb134d 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -9,7 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
>  obj-$(CONFIG_SUSPEND)		+= suspend.o
>  obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
>  obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
> -				   block_io.o
> +				   block_io.o compress.o
>  obj-$(CONFIG_SUSPEND_NVS)	+= nvs.o
>  
>  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
> diff --git a/kernel/power/compress.c b/kernel/power/compress.c
> new file mode 100644
> index 0000000..45725ea
> --- /dev/null
> +++ b/kernel/power/compress.c
> @@ -0,0 +1,210 @@
> +/*
> + * linux/kernel/power/compress.c
> + *
> + * This file provides functions for (optionally) compressing an
> + * image as it is being written and decompressing it at resume.
> + *
> + * Copyright (C) 2003-2010 Nigel Cunningham <nigel@tuxonice.net>
> + *
> + * This file is released under the GPLv2.
> + *
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/lzo.h>
> +#include <linux/vmalloc.h>
> +
> +#include "power.h"
> +#include "swap.h"
> +
> +/* We need to remember how much compressed data we need to read. */
> +#define LZO_HEADER	sizeof(size_t)
> +
> +/* Number of pages/bytes we'll compress at one time. */
> +#define LZO_UNC_PAGES	32
> +#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
> +
> +/* Number of pages/bytes we need for compressed data (worst case). */
> +#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
> +			             LZO_HEADER, PAGE_SIZE)
> +#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
> +
> +static size_t off, unc_len, cmp_len;
> +static unsigned char *unc, *cmp, *wrk, *page;
> +
> +void compress_image_cleanup(void)
> +{
> +	if (cmp) {
> +		vfree(cmp);
> +		cmp = NULL;
> +	}
> +
> +	if (unc) {
> +		vfree(unc);
> +		unc = NULL;
> +	}
> +
> +	if (wrk) {
> +		vfree(wrk);
> +		wrk = NULL;
> +	}
> +
> +	if (page) {
> +		free_page((unsigned long)page);
> +		page = NULL;
> +	}
> +}
> +
> +int compress_image_init(void)
> +{
> +	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
> +	if (!page) {
> +		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
> +		return -ENOMEM;
> +	}
> +
> +	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
> +	unc = vmalloc(LZO_UNC_SIZE);
> +	cmp = vmalloc(LZO_CMP_SIZE);
> +
> +	if (!wrk || !unc || !cmp) {
> +		printk(KERN_ERR "PM: Failed to allocate memory for (de)compression.\n");
> +		compress_image_cleanup();
> +		return -ENOMEM;
> +	}
> +
> +	off = 0;
> +
> +	return 0;
> +}
> +
> +static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
> +{
> +	int ret;
> +
> +	if (!off)
> +		return 0;
> +
> +	unc_len = off;
> +	ret = lzo1x_1_compress(unc, unc_len, cmp + LZO_HEADER, &cmp_len, wrk);
> +
> +	if (ret < 0) {
> +		printk(KERN_ERR "PM: LZO compression failed\n");
> +		return -EIO;
> +	}
> +
> +	if (unlikely(!cmp_len ||
> +	             cmp_len > lzo1x_worst_compress(unc_len))) {
> +		printk(KERN_ERR "PM: Invalid LZO compressed length\n");
> +		return -EIO;
> +	}
> +
> +	*(size_t *)cmp = cmp_len;
> +
> +	/*
> +	 * Given we are writing one page at a time to disk, we copy
> +	 * that much from the buffer, although the last bit will likely
> +	 * be smaller than full page. This is OK - we saved the length
> +	 * of the compressed data, so any garbage at the end will be
> +	 * discarded when we read it.
> +	 */
> +	for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
> +		memcpy(page, cmp + off, PAGE_SIZE);
> +
> +		ret = swap_write_page(handle, page, bio);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	off = 0;
> +	return 0;
> +}
> +
> +int compress_write(struct swap_map_handle *handle, char *buf, struct bio **bio,
> +		int flags)
> +{
> +	int ret = 0;
> +
> +	if (flags & SF_NOCOMPRESS_MODE)
> +		return swap_write_page(handle, buf, bio);
> +
> +	if (off == LZO_UNC_SIZE)
> +		ret = compress_and_write(handle, bio);
> +
> +	memcpy(unc + off, buf, PAGE_SIZE);
> +	off += PAGE_SIZE;
> +	return ret;
> +}

This one doesn't really good to me.  What I'd prefer would be to have a
structure of "swap operations" pointers like ->start(), ->write_data(),
->read_data(), and ->finish() that will point to the functions in this file
(if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
otherwise.  That would reduce the number of the
(flags & SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
in code that's easier to follow.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-09-27  5:43 ` Nigel Cunningham
  2010-09-27 20:27   ` Rafael J. Wysocki
@ 2010-09-27 20:27   ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-09-27 20:27 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Separate compression support out into its own file, removing in
> the process the duplication of the load_image and save_image
> functions and some #includes from swap.c that are no longer
> needed.
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>

If you're at it, I'd like to do something slightly different.  Explained below.

> ---
>  kernel/power/Makefile   |    2 +-
>  kernel/power/compress.c |  210 +++++++++++++++++++++++++++++
>  kernel/power/compress.h |   23 +++
>  kernel/power/swap.c     |  339 +++++------------------------------------------
>  kernel/power/swap.h     |   28 ++++
>  5 files changed, 296 insertions(+), 306 deletions(-)
>  create mode 100644 kernel/power/compress.c
>  create mode 100644 kernel/power/compress.h
>  create mode 100644 kernel/power/swap.h
> 
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index f9063c6..2eb134d 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -9,7 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
>  obj-$(CONFIG_SUSPEND)		+= suspend.o
>  obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
>  obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
> -				   block_io.o
> +				   block_io.o compress.o
>  obj-$(CONFIG_SUSPEND_NVS)	+= nvs.o
>  
>  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
> diff --git a/kernel/power/compress.c b/kernel/power/compress.c
> new file mode 100644
> index 0000000..45725ea
> --- /dev/null
> +++ b/kernel/power/compress.c
> @@ -0,0 +1,210 @@
> +/*
> + * linux/kernel/power/compress.c
> + *
> + * This file provides functions for (optionally) compressing an
> + * image as it is being written and decompressing it at resume.
> + *
> + * Copyright (C) 2003-2010 Nigel Cunningham <nigel@tuxonice.net>
> + *
> + * This file is released under the GPLv2.
> + *
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/lzo.h>
> +#include <linux/vmalloc.h>
> +
> +#include "power.h"
> +#include "swap.h"
> +
> +/* We need to remember how much compressed data we need to read. */
> +#define LZO_HEADER	sizeof(size_t)
> +
> +/* Number of pages/bytes we'll compress at one time. */
> +#define LZO_UNC_PAGES	32
> +#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
> +
> +/* Number of pages/bytes we need for compressed data (worst case). */
> +#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
> +			             LZO_HEADER, PAGE_SIZE)
> +#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
> +
> +static size_t off, unc_len, cmp_len;
> +static unsigned char *unc, *cmp, *wrk, *page;
> +
> +void compress_image_cleanup(void)
> +{
> +	if (cmp) {
> +		vfree(cmp);
> +		cmp = NULL;
> +	}
> +
> +	if (unc) {
> +		vfree(unc);
> +		unc = NULL;
> +	}
> +
> +	if (wrk) {
> +		vfree(wrk);
> +		wrk = NULL;
> +	}
> +
> +	if (page) {
> +		free_page((unsigned long)page);
> +		page = NULL;
> +	}
> +}
> +
> +int compress_image_init(void)
> +{
> +	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
> +	if (!page) {
> +		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
> +		return -ENOMEM;
> +	}
> +
> +	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
> +	unc = vmalloc(LZO_UNC_SIZE);
> +	cmp = vmalloc(LZO_CMP_SIZE);
> +
> +	if (!wrk || !unc || !cmp) {
> +		printk(KERN_ERR "PM: Failed to allocate memory for (de)compression.\n");
> +		compress_image_cleanup();
> +		return -ENOMEM;
> +	}
> +
> +	off = 0;
> +
> +	return 0;
> +}
> +
> +static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
> +{
> +	int ret;
> +
> +	if (!off)
> +		return 0;
> +
> +	unc_len = off;
> +	ret = lzo1x_1_compress(unc, unc_len, cmp + LZO_HEADER, &cmp_len, wrk);
> +
> +	if (ret < 0) {
> +		printk(KERN_ERR "PM: LZO compression failed\n");
> +		return -EIO;
> +	}
> +
> +	if (unlikely(!cmp_len ||
> +	             cmp_len > lzo1x_worst_compress(unc_len))) {
> +		printk(KERN_ERR "PM: Invalid LZO compressed length\n");
> +		return -EIO;
> +	}
> +
> +	*(size_t *)cmp = cmp_len;
> +
> +	/*
> +	 * Given we are writing one page at a time to disk, we copy
> +	 * that much from the buffer, although the last bit will likely
> +	 * be smaller than full page. This is OK - we saved the length
> +	 * of the compressed data, so any garbage at the end will be
> +	 * discarded when we read it.
> +	 */
> +	for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
> +		memcpy(page, cmp + off, PAGE_SIZE);
> +
> +		ret = swap_write_page(handle, page, bio);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	off = 0;
> +	return 0;
> +}
> +
> +int compress_write(struct swap_map_handle *handle, char *buf, struct bio **bio,
> +		int flags)
> +{
> +	int ret = 0;
> +
> +	if (flags & SF_NOCOMPRESS_MODE)
> +		return swap_write_page(handle, buf, bio);
> +
> +	if (off == LZO_UNC_SIZE)
> +		ret = compress_and_write(handle, bio);
> +
> +	memcpy(unc + off, buf, PAGE_SIZE);
> +	off += PAGE_SIZE;
> +	return ret;
> +}

This one doesn't really good to me.  What I'd prefer would be to have a
structure of "swap operations" pointers like ->start(), ->write_data(),
->read_data(), and ->finish() that will point to the functions in this file
(if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
otherwise.  That would reduce the number of the
(flags & SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
in code that's easier to follow.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-09-27 20:27   ` Rafael J. Wysocki
  2010-09-27 20:32     ` Nigel Cunningham
@ 2010-09-27 20:32     ` Nigel Cunningham
  2010-10-01 21:28       ` Rafael J. Wysocki
  2010-10-01 21:28       ` Rafael J. Wysocki
  1 sibling, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27 20:32 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 28/09/10 06:27, Rafael J. Wysocki wrote:
> On Monday, September 27, 2010, Nigel Cunningham wrote:
>> Separate compression support out into its own file, removing in
>> the process the duplication of the load_image and save_image
>> functions and some #includes from swap.c that are no longer
>> needed.
>>
>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>
> If you're at it, I'd like to do something slightly different.  Explained below.
>
>> ---
>>   kernel/power/Makefile   |    2 +-
>>   kernel/power/compress.c |  210 +++++++++++++++++++++++++++++
>>   kernel/power/compress.h |   23 +++
>>   kernel/power/swap.c     |  339 +++++------------------------------------------
>>   kernel/power/swap.h     |   28 ++++
>>   5 files changed, 296 insertions(+), 306 deletions(-)
>>   create mode 100644 kernel/power/compress.c
>>   create mode 100644 kernel/power/compress.h
>>   create mode 100644 kernel/power/swap.h
>>
>> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
>> index f9063c6..2eb134d 100644
>> --- a/kernel/power/Makefile
>> +++ b/kernel/power/Makefile
>> @@ -9,7 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
>>   obj-$(CONFIG_SUSPEND)		+= suspend.o
>>   obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
>>   obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
>> -				   block_io.o
>> +				   block_io.o compress.o
>>   obj-$(CONFIG_SUSPEND_NVS)	+= nvs.o
>>
>>   obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
>> diff --git a/kernel/power/compress.c b/kernel/power/compress.c
>> new file mode 100644
>> index 0000000..45725ea
>> --- /dev/null
>> +++ b/kernel/power/compress.c
>> @@ -0,0 +1,210 @@
>> +/*
>> + * linux/kernel/power/compress.c
>> + *
>> + * This file provides functions for (optionally) compressing an
>> + * image as it is being written and decompressing it at resume.
>> + *
>> + * Copyright (C) 2003-2010 Nigel Cunningham<nigel@tuxonice.net>
>> + *
>> + * This file is released under the GPLv2.
>> + *
>> + */
>> +
>> +#include<linux/slab.h>
>> +#include<linux/lzo.h>
>> +#include<linux/vmalloc.h>
>> +
>> +#include "power.h"
>> +#include "swap.h"
>> +
>> +/* We need to remember how much compressed data we need to read. */
>> +#define LZO_HEADER	sizeof(size_t)
>> +
>> +/* Number of pages/bytes we'll compress at one time. */
>> +#define LZO_UNC_PAGES	32
>> +#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
>> +
>> +/* Number of pages/bytes we need for compressed data (worst case). */
>> +#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
>> +			             LZO_HEADER, PAGE_SIZE)
>> +#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
>> +
>> +static size_t off, unc_len, cmp_len;
>> +static unsigned char *unc, *cmp, *wrk, *page;
>> +
>> +void compress_image_cleanup(void)
>> +{
>> +	if (cmp) {
>> +		vfree(cmp);
>> +		cmp = NULL;
>> +	}
>> +
>> +	if (unc) {
>> +		vfree(unc);
>> +		unc = NULL;
>> +	}
>> +
>> +	if (wrk) {
>> +		vfree(wrk);
>> +		wrk = NULL;
>> +	}
>> +
>> +	if (page) {
>> +		free_page((unsigned long)page);
>> +		page = NULL;
>> +	}
>> +}
>> +
>> +int compress_image_init(void)
>> +{
>> +	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
>> +	if (!page) {
>> +		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
>> +	unc = vmalloc(LZO_UNC_SIZE);
>> +	cmp = vmalloc(LZO_CMP_SIZE);
>> +
>> +	if (!wrk || !unc || !cmp) {
>> +		printk(KERN_ERR "PM: Failed to allocate memory for (de)compression.\n");
>> +		compress_image_cleanup();
>> +		return -ENOMEM;
>> +	}
>> +
>> +	off = 0;
>> +
>> +	return 0;
>> +}
>> +
>> +static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
>> +{
>> +	int ret;
>> +
>> +	if (!off)
>> +		return 0;
>> +
>> +	unc_len = off;
>> +	ret = lzo1x_1_compress(unc, unc_len, cmp + LZO_HEADER,&cmp_len, wrk);
>> +
>> +	if (ret<  0) {
>> +		printk(KERN_ERR "PM: LZO compression failed\n");
>> +		return -EIO;
>> +	}
>> +
>> +	if (unlikely(!cmp_len ||
>> +	             cmp_len>  lzo1x_worst_compress(unc_len))) {
>> +		printk(KERN_ERR "PM: Invalid LZO compressed length\n");
>> +		return -EIO;
>> +	}
>> +
>> +	*(size_t *)cmp = cmp_len;
>> +
>> +	/*
>> +	 * Given we are writing one page at a time to disk, we copy
>> +	 * that much from the buffer, although the last bit will likely
>> +	 * be smaller than full page. This is OK - we saved the length
>> +	 * of the compressed data, so any garbage at the end will be
>> +	 * discarded when we read it.
>> +	 */
>> +	for (off = 0; off<  LZO_HEADER + cmp_len; off += PAGE_SIZE) {
>> +		memcpy(page, cmp + off, PAGE_SIZE);
>> +
>> +		ret = swap_write_page(handle, page, bio);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	off = 0;
>> +	return 0;
>> +}
>> +
>> +int compress_write(struct swap_map_handle *handle, char *buf, struct bio **bio,
>> +		int flags)
>> +{
>> +	int ret = 0;
>> +
>> +	if (flags&  SF_NOCOMPRESS_MODE)
>> +		return swap_write_page(handle, buf, bio);
>> +
>> +	if (off == LZO_UNC_SIZE)
>> +		ret = compress_and_write(handle, bio);
>> +
>> +	memcpy(unc + off, buf, PAGE_SIZE);
>> +	off += PAGE_SIZE;
>> +	return ret;
>> +}
>
> This one doesn't really good to me.  What I'd prefer would be to have a
> structure of "swap operations" pointers like ->start(), ->write_data(),
> ->read_data(), and ->finish() that will point to the functions in this file
> (if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
> otherwise.  That would reduce the number of the
> (flags&  SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
> in code that's easier to follow.

Me too. I was heading in that direction, but not doing it in one step. 
I'll happily change that.

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-09-27 20:27   ` Rafael J. Wysocki
@ 2010-09-27 20:32     ` Nigel Cunningham
  2010-09-27 20:32     ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27 20:32 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 28/09/10 06:27, Rafael J. Wysocki wrote:
> On Monday, September 27, 2010, Nigel Cunningham wrote:
>> Separate compression support out into its own file, removing in
>> the process the duplication of the load_image and save_image
>> functions and some #includes from swap.c that are no longer
>> needed.
>>
>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>
> If you're at it, I'd like to do something slightly different.  Explained below.
>
>> ---
>>   kernel/power/Makefile   |    2 +-
>>   kernel/power/compress.c |  210 +++++++++++++++++++++++++++++
>>   kernel/power/compress.h |   23 +++
>>   kernel/power/swap.c     |  339 +++++------------------------------------------
>>   kernel/power/swap.h     |   28 ++++
>>   5 files changed, 296 insertions(+), 306 deletions(-)
>>   create mode 100644 kernel/power/compress.c
>>   create mode 100644 kernel/power/compress.h
>>   create mode 100644 kernel/power/swap.h
>>
>> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
>> index f9063c6..2eb134d 100644
>> --- a/kernel/power/Makefile
>> +++ b/kernel/power/Makefile
>> @@ -9,7 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
>>   obj-$(CONFIG_SUSPEND)		+= suspend.o
>>   obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
>>   obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
>> -				   block_io.o
>> +				   block_io.o compress.o
>>   obj-$(CONFIG_SUSPEND_NVS)	+= nvs.o
>>
>>   obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
>> diff --git a/kernel/power/compress.c b/kernel/power/compress.c
>> new file mode 100644
>> index 0000000..45725ea
>> --- /dev/null
>> +++ b/kernel/power/compress.c
>> @@ -0,0 +1,210 @@
>> +/*
>> + * linux/kernel/power/compress.c
>> + *
>> + * This file provides functions for (optionally) compressing an
>> + * image as it is being written and decompressing it at resume.
>> + *
>> + * Copyright (C) 2003-2010 Nigel Cunningham<nigel@tuxonice.net>
>> + *
>> + * This file is released under the GPLv2.
>> + *
>> + */
>> +
>> +#include<linux/slab.h>
>> +#include<linux/lzo.h>
>> +#include<linux/vmalloc.h>
>> +
>> +#include "power.h"
>> +#include "swap.h"
>> +
>> +/* We need to remember how much compressed data we need to read. */
>> +#define LZO_HEADER	sizeof(size_t)
>> +
>> +/* Number of pages/bytes we'll compress at one time. */
>> +#define LZO_UNC_PAGES	32
>> +#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
>> +
>> +/* Number of pages/bytes we need for compressed data (worst case). */
>> +#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
>> +			             LZO_HEADER, PAGE_SIZE)
>> +#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
>> +
>> +static size_t off, unc_len, cmp_len;
>> +static unsigned char *unc, *cmp, *wrk, *page;
>> +
>> +void compress_image_cleanup(void)
>> +{
>> +	if (cmp) {
>> +		vfree(cmp);
>> +		cmp = NULL;
>> +	}
>> +
>> +	if (unc) {
>> +		vfree(unc);
>> +		unc = NULL;
>> +	}
>> +
>> +	if (wrk) {
>> +		vfree(wrk);
>> +		wrk = NULL;
>> +	}
>> +
>> +	if (page) {
>> +		free_page((unsigned long)page);
>> +		page = NULL;
>> +	}
>> +}
>> +
>> +int compress_image_init(void)
>> +{
>> +	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
>> +	if (!page) {
>> +		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
>> +	unc = vmalloc(LZO_UNC_SIZE);
>> +	cmp = vmalloc(LZO_CMP_SIZE);
>> +
>> +	if (!wrk || !unc || !cmp) {
>> +		printk(KERN_ERR "PM: Failed to allocate memory for (de)compression.\n");
>> +		compress_image_cleanup();
>> +		return -ENOMEM;
>> +	}
>> +
>> +	off = 0;
>> +
>> +	return 0;
>> +}
>> +
>> +static int compress_and_write(struct swap_map_handle *handle, struct bio **bio)
>> +{
>> +	int ret;
>> +
>> +	if (!off)
>> +		return 0;
>> +
>> +	unc_len = off;
>> +	ret = lzo1x_1_compress(unc, unc_len, cmp + LZO_HEADER,&cmp_len, wrk);
>> +
>> +	if (ret<  0) {
>> +		printk(KERN_ERR "PM: LZO compression failed\n");
>> +		return -EIO;
>> +	}
>> +
>> +	if (unlikely(!cmp_len ||
>> +	             cmp_len>  lzo1x_worst_compress(unc_len))) {
>> +		printk(KERN_ERR "PM: Invalid LZO compressed length\n");
>> +		return -EIO;
>> +	}
>> +
>> +	*(size_t *)cmp = cmp_len;
>> +
>> +	/*
>> +	 * Given we are writing one page at a time to disk, we copy
>> +	 * that much from the buffer, although the last bit will likely
>> +	 * be smaller than full page. This is OK - we saved the length
>> +	 * of the compressed data, so any garbage at the end will be
>> +	 * discarded when we read it.
>> +	 */
>> +	for (off = 0; off<  LZO_HEADER + cmp_len; off += PAGE_SIZE) {
>> +		memcpy(page, cmp + off, PAGE_SIZE);
>> +
>> +		ret = swap_write_page(handle, page, bio);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	off = 0;
>> +	return 0;
>> +}
>> +
>> +int compress_write(struct swap_map_handle *handle, char *buf, struct bio **bio,
>> +		int flags)
>> +{
>> +	int ret = 0;
>> +
>> +	if (flags&  SF_NOCOMPRESS_MODE)
>> +		return swap_write_page(handle, buf, bio);
>> +
>> +	if (off == LZO_UNC_SIZE)
>> +		ret = compress_and_write(handle, bio);
>> +
>> +	memcpy(unc + off, buf, PAGE_SIZE);
>> +	off += PAGE_SIZE;
>> +	return ret;
>> +}
>
> This one doesn't really good to me.  What I'd prefer would be to have a
> structure of "swap operations" pointers like ->start(), ->write_data(),
> ->read_data(), and ->finish() that will point to the functions in this file
> (if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
> otherwise.  That would reduce the number of the
> (flags&  SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
> in code that's easier to follow.

Me too. I was heading in that direction, but not doing it in one step. 
I'll happily change that.

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27 20:26     ` Nigel Cunningham
@ 2010-09-27 20:49       ` Rafael J. Wysocki
  2010-09-27 21:05         ` Nigel Cunningham
  2010-09-27 21:05         ` Nigel Cunningham
  2010-09-27 20:49       ` Rafael J. Wysocki
  1 sibling, 2 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-09-27 20:49 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Hi.
> 
> On 28/09/10 06:06, Rafael J. Wysocki wrote:
> > On Monday, September 27, 2010, Nigel Cunningham wrote:
> >> Record the speed at which the image is written and read, and
> >> display it to the user post-resume.
> >>
> >> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
> >> ---
> >>   kernel/power/hibernate.c |   11 ++++++++++-
> >>   kernel/power/power.h     |    3 ++-
> >>   kernel/power/swap.c      |   14 +++++++++++---
> >>   3 files changed, 23 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> >> index 6c9c9dc..0cd1f05 100644
> >> --- a/kernel/power/hibernate.c
> >> +++ b/kernel/power/hibernate.c
> >> @@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
> >>    *	@msg -		introductory message to print
> >>    */
> >>
> >> -void swsusp_show_speed(struct timeval *start, struct timeval *stop,
> >> +int swsusp_show_speed(struct timeval *start, struct timeval *stop,
> >>   			unsigned nr_pages, char *msg)
> >>   {
> >>   	s64 elapsed_centisecs64;
> >> @@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
> >>   			msg, k,
> >>   			centisecs / 100, centisecs % 100,
> >>   			kps / 1000, (kps % 1000) / 10);
> >> +	return kps / 1000;
> >>   }
> >>
> >>   /**
> >> @@ -648,6 +649,14 @@ int hibernate(void)
> >>   			power_down();
> >>   	} else {
> >>   		pr_debug("PM: Image restored successfully.\n");
> >> +		if (write_speed)
> >> +			pr_debug("PM: Image written at %u MB/s.\n",
> >> +					(u8) write_speed);
> >> +		write_speed = 0;
> >> +		if (read_speed)
> >> +			pr_debug("PM: Image read at %u MB/s.\n",
> >> +					(u8) read_speed);
> >> +		read_speed = 0;
> >>   	}
> >>
> >>    Thaw:
> >> diff --git a/kernel/power/power.h b/kernel/power/power.h
> >> index 03634be..22f8607 100644
> >> --- a/kernel/power/power.h
> >> +++ b/kernel/power/power.h
> >> @@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
> >>   extern int hibernation_restore(int platform_mode);
> >>   extern int hibernation_platform_enter(void);
> >>
> >> +extern char __nosavedata write_speed, read_speed;
> >>   #else /* !CONFIG_HIBERNATION */
> >>
> >>   static inline void hibernate_image_size_init(void) {}
> >> @@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
> >>
> >>   struct timeval;
> >>   /* kernel/power/swsusp.c */
> >> -extern void swsusp_show_speed(struct timeval *, struct timeval *,
> >> +extern int swsusp_show_speed(struct timeval *, struct timeval *,
> >>   				unsigned int, char *);
> >>
> >>   #ifdef CONFIG_SUSPEND
> >> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
> >> index 3c01105..caf4db8 100644
> >> --- a/kernel/power/swap.c
> >> +++ b/kernel/power/swap.c
> >> @@ -45,7 +45,8 @@ struct swap_map_page {
> >>   };
> >>
> >>   struct swsusp_header {
> >> -	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
> >> +	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
> >> +	char write_speed;
> >>   	sector_t image;
> >>   	unsigned int flags;	/* Flags to pass to the "boot" kernel */
> >>   	char	orig_sig[10];
> >> @@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
> >>
> >>   static unsigned short root_swap = 0xffff;
> >>   struct block_device *hib_resume_bdev;
> >> +char __nosavedata write_speed, read_speed;
> >
> > I really should have noticed that earlier, but I don't really like __nosavedata
> > being used here.  In fact, it shouldn't be used at all any more, because it's
> > meaningless on x86_64.
> 
> Really? Okay. When did that change?

Well, some time ago, looks like in 2007, but the files changed and were moving
around, so it's hard to say exactly.

> > I'm not sure how to implement that without __nosavedata, but please don't
> > use it.  Sorry aboiut that.
> 
> Well then, for now, let's drop that patch then. At least it's got us the 
> numbers we needed to see these patches are useful. Longer term, I'll do 
> what I do in TuxOnIce and allocate a page while writing the image, store 
> it's location in the image header and use it the transfer information 
> from the boot kernel to the resumed kernel. (Essentially the same thing, 
> except without the special section).

The problem is that on x86_64 the boot kernel may be completely different
from the image kernel (different version, different configuration), so there is
no guarantee that your page frame allocated while writing the image would be
available to the boot kernel (it may contain the kernel code, for example).

You'd really need to replace one of the image pages with  something prepared
while the image was being read.  For that, you'd need to allocate a page before
creating the image and pass its PFN in the image header.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27 20:26     ` Nigel Cunningham
  2010-09-27 20:49       ` Rafael J. Wysocki
@ 2010-09-27 20:49       ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-09-27 20:49 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Hi.
> 
> On 28/09/10 06:06, Rafael J. Wysocki wrote:
> > On Monday, September 27, 2010, Nigel Cunningham wrote:
> >> Record the speed at which the image is written and read, and
> >> display it to the user post-resume.
> >>
> >> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
> >> ---
> >>   kernel/power/hibernate.c |   11 ++++++++++-
> >>   kernel/power/power.h     |    3 ++-
> >>   kernel/power/swap.c      |   14 +++++++++++---
> >>   3 files changed, 23 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> >> index 6c9c9dc..0cd1f05 100644
> >> --- a/kernel/power/hibernate.c
> >> +++ b/kernel/power/hibernate.c
> >> @@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
> >>    *	@msg -		introductory message to print
> >>    */
> >>
> >> -void swsusp_show_speed(struct timeval *start, struct timeval *stop,
> >> +int swsusp_show_speed(struct timeval *start, struct timeval *stop,
> >>   			unsigned nr_pages, char *msg)
> >>   {
> >>   	s64 elapsed_centisecs64;
> >> @@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
> >>   			msg, k,
> >>   			centisecs / 100, centisecs % 100,
> >>   			kps / 1000, (kps % 1000) / 10);
> >> +	return kps / 1000;
> >>   }
> >>
> >>   /**
> >> @@ -648,6 +649,14 @@ int hibernate(void)
> >>   			power_down();
> >>   	} else {
> >>   		pr_debug("PM: Image restored successfully.\n");
> >> +		if (write_speed)
> >> +			pr_debug("PM: Image written at %u MB/s.\n",
> >> +					(u8) write_speed);
> >> +		write_speed = 0;
> >> +		if (read_speed)
> >> +			pr_debug("PM: Image read at %u MB/s.\n",
> >> +					(u8) read_speed);
> >> +		read_speed = 0;
> >>   	}
> >>
> >>    Thaw:
> >> diff --git a/kernel/power/power.h b/kernel/power/power.h
> >> index 03634be..22f8607 100644
> >> --- a/kernel/power/power.h
> >> +++ b/kernel/power/power.h
> >> @@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
> >>   extern int hibernation_restore(int platform_mode);
> >>   extern int hibernation_platform_enter(void);
> >>
> >> +extern char __nosavedata write_speed, read_speed;
> >>   #else /* !CONFIG_HIBERNATION */
> >>
> >>   static inline void hibernate_image_size_init(void) {}
> >> @@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
> >>
> >>   struct timeval;
> >>   /* kernel/power/swsusp.c */
> >> -extern void swsusp_show_speed(struct timeval *, struct timeval *,
> >> +extern int swsusp_show_speed(struct timeval *, struct timeval *,
> >>   				unsigned int, char *);
> >>
> >>   #ifdef CONFIG_SUSPEND
> >> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
> >> index 3c01105..caf4db8 100644
> >> --- a/kernel/power/swap.c
> >> +++ b/kernel/power/swap.c
> >> @@ -45,7 +45,8 @@ struct swap_map_page {
> >>   };
> >>
> >>   struct swsusp_header {
> >> -	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
> >> +	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
> >> +	char write_speed;
> >>   	sector_t image;
> >>   	unsigned int flags;	/* Flags to pass to the "boot" kernel */
> >>   	char	orig_sig[10];
> >> @@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
> >>
> >>   static unsigned short root_swap = 0xffff;
> >>   struct block_device *hib_resume_bdev;
> >> +char __nosavedata write_speed, read_speed;
> >
> > I really should have noticed that earlier, but I don't really like __nosavedata
> > being used here.  In fact, it shouldn't be used at all any more, because it's
> > meaningless on x86_64.
> 
> Really? Okay. When did that change?

Well, some time ago, looks like in 2007, but the files changed and were moving
around, so it's hard to say exactly.

> > I'm not sure how to implement that without __nosavedata, but please don't
> > use it.  Sorry aboiut that.
> 
> Well then, for now, let's drop that patch then. At least it's got us the 
> numbers we needed to see these patches are useful. Longer term, I'll do 
> what I do in TuxOnIce and allocate a page while writing the image, store 
> it's location in the image header and use it the transfer information 
> from the boot kernel to the resumed kernel. (Essentially the same thing, 
> except without the special section).

The problem is that on x86_64 the boot kernel may be completely different
from the image kernel (different version, different configuration), so there is
no guarantee that your page frame allocated while writing the image would be
available to the boot kernel (it may contain the kernel code, for example).

You'd really need to replace one of the image pages with  something prepared
while the image was being read.  For that, you'd need to allocate a page before
creating the image and pass its PFN in the image header.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27 20:49       ` Rafael J. Wysocki
@ 2010-09-27 21:05         ` Nigel Cunningham
  2010-09-27 21:16           ` Rafael J. Wysocki
  2010-09-27 21:16           ` Rafael J. Wysocki
  2010-09-27 21:05         ` Nigel Cunningham
  1 sibling, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27 21:05 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 28/09/10 06:49, Rafael J. Wysocki wrote:
> On Monday, September 27, 2010, Nigel Cunningham wrote:
>> Hi.
>>
>> On 28/09/10 06:06, Rafael J. Wysocki wrote:
>>> On Monday, September 27, 2010, Nigel Cunningham wrote:
>>>> Record the speed at which the image is written and read, and
>>>> display it to the user post-resume.
>>>>
>>>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>>>> ---
>>>>    kernel/power/hibernate.c |   11 ++++++++++-
>>>>    kernel/power/power.h     |    3 ++-
>>>>    kernel/power/swap.c      |   14 +++++++++++---
>>>>    3 files changed, 23 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
>>>> index 6c9c9dc..0cd1f05 100644
>>>> --- a/kernel/power/hibernate.c
>>>> +++ b/kernel/power/hibernate.c
>>>> @@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
>>>>     *	@msg -		introductory message to print
>>>>     */
>>>>
>>>> -void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>>> +int swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>>>    			unsigned nr_pages, char *msg)
>>>>    {
>>>>    	s64 elapsed_centisecs64;
>>>> @@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>>>    			msg, k,
>>>>    			centisecs / 100, centisecs % 100,
>>>>    			kps / 1000, (kps % 1000) / 10);
>>>> +	return kps / 1000;
>>>>    }
>>>>
>>>>    /**
>>>> @@ -648,6 +649,14 @@ int hibernate(void)
>>>>    			power_down();
>>>>    	} else {
>>>>    		pr_debug("PM: Image restored successfully.\n");
>>>> +		if (write_speed)
>>>> +			pr_debug("PM: Image written at %u MB/s.\n",
>>>> +					(u8) write_speed);
>>>> +		write_speed = 0;
>>>> +		if (read_speed)
>>>> +			pr_debug("PM: Image read at %u MB/s.\n",
>>>> +					(u8) read_speed);
>>>> +		read_speed = 0;
>>>>    	}
>>>>
>>>>     Thaw:
>>>> diff --git a/kernel/power/power.h b/kernel/power/power.h
>>>> index 03634be..22f8607 100644
>>>> --- a/kernel/power/power.h
>>>> +++ b/kernel/power/power.h
>>>> @@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
>>>>    extern int hibernation_restore(int platform_mode);
>>>>    extern int hibernation_platform_enter(void);
>>>>
>>>> +extern char __nosavedata write_speed, read_speed;
>>>>    #else /* !CONFIG_HIBERNATION */
>>>>
>>>>    static inline void hibernate_image_size_init(void) {}
>>>> @@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
>>>>
>>>>    struct timeval;
>>>>    /* kernel/power/swsusp.c */
>>>> -extern void swsusp_show_speed(struct timeval *, struct timeval *,
>>>> +extern int swsusp_show_speed(struct timeval *, struct timeval *,
>>>>    				unsigned int, char *);
>>>>
>>>>    #ifdef CONFIG_SUSPEND
>>>> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
>>>> index 3c01105..caf4db8 100644
>>>> --- a/kernel/power/swap.c
>>>> +++ b/kernel/power/swap.c
>>>> @@ -45,7 +45,8 @@ struct swap_map_page {
>>>>    };
>>>>
>>>>    struct swsusp_header {
>>>> -	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
>>>> +	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
>>>> +	char write_speed;
>>>>    	sector_t image;
>>>>    	unsigned int flags;	/* Flags to pass to the "boot" kernel */
>>>>    	char	orig_sig[10];
>>>> @@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
>>>>
>>>>    static unsigned short root_swap = 0xffff;
>>>>    struct block_device *hib_resume_bdev;
>>>> +char __nosavedata write_speed, read_speed;
>>>
>>> I really should have noticed that earlier, but I don't really like __nosavedata
>>> being used here.  In fact, it shouldn't be used at all any more, because it's
>>> meaningless on x86_64.
>>
>> Really? Okay. When did that change?
>
> Well, some time ago, looks like in 2007, but the files changed and were moving
> around, so it's hard to say exactly.

Hmm. Really failed to notice that one, didn't I? :)

>>> I'm not sure how to implement that without __nosavedata, but please don't
>>> use it.  Sorry aboiut that.
>>
>> Well then, for now, let's drop that patch then. At least it's got us the
>> numbers we needed to see these patches are useful. Longer term, I'll do
>> what I do in TuxOnIce and allocate a page while writing the image, store
>> it's location in the image header and use it the transfer information
>> from the boot kernel to the resumed kernel. (Essentially the same thing,
>> except without the special section).
>
> The problem is that on x86_64 the boot kernel may be completely different
> from the image kernel (different version, different configuration), so there is
> no guarantee that your page frame allocated while writing the image would be
> available to the boot kernel (it may contain the kernel code, for example).
>
> You'd really need to replace one of the image pages with  something prepared
> while the image was being read.  For that, you'd need to allocate a page before
> creating the image and pass its PFN in the image header.

Yes - that's what I'm doing. Maybe that's why the __nosavedata changes 
you mentioned above haven't bitten me.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27 20:49       ` Rafael J. Wysocki
  2010-09-27 21:05         ` Nigel Cunningham
@ 2010-09-27 21:05         ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27 21:05 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 28/09/10 06:49, Rafael J. Wysocki wrote:
> On Monday, September 27, 2010, Nigel Cunningham wrote:
>> Hi.
>>
>> On 28/09/10 06:06, Rafael J. Wysocki wrote:
>>> On Monday, September 27, 2010, Nigel Cunningham wrote:
>>>> Record the speed at which the image is written and read, and
>>>> display it to the user post-resume.
>>>>
>>>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>>>> ---
>>>>    kernel/power/hibernate.c |   11 ++++++++++-
>>>>    kernel/power/power.h     |    3 ++-
>>>>    kernel/power/swap.c      |   14 +++++++++++---
>>>>    3 files changed, 23 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
>>>> index 6c9c9dc..0cd1f05 100644
>>>> --- a/kernel/power/hibernate.c
>>>> +++ b/kernel/power/hibernate.c
>>>> @@ -212,7 +212,7 @@ static void platform_recover(int platform_mode)
>>>>     *	@msg -		introductory message to print
>>>>     */
>>>>
>>>> -void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>>> +int swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>>>    			unsigned nr_pages, char *msg)
>>>>    {
>>>>    	s64 elapsed_centisecs64;
>>>> @@ -231,6 +231,7 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop,
>>>>    			msg, k,
>>>>    			centisecs / 100, centisecs % 100,
>>>>    			kps / 1000, (kps % 1000) / 10);
>>>> +	return kps / 1000;
>>>>    }
>>>>
>>>>    /**
>>>> @@ -648,6 +649,14 @@ int hibernate(void)
>>>>    			power_down();
>>>>    	} else {
>>>>    		pr_debug("PM: Image restored successfully.\n");
>>>> +		if (write_speed)
>>>> +			pr_debug("PM: Image written at %u MB/s.\n",
>>>> +					(u8) write_speed);
>>>> +		write_speed = 0;
>>>> +		if (read_speed)
>>>> +			pr_debug("PM: Image read at %u MB/s.\n",
>>>> +					(u8) read_speed);
>>>> +		read_speed = 0;
>>>>    	}
>>>>
>>>>     Thaw:
>>>> diff --git a/kernel/power/power.h b/kernel/power/power.h
>>>> index 03634be..22f8607 100644
>>>> --- a/kernel/power/power.h
>>>> +++ b/kernel/power/power.h
>>>> @@ -53,6 +53,7 @@ extern int hibernation_snapshot(int platform_mode);
>>>>    extern int hibernation_restore(int platform_mode);
>>>>    extern int hibernation_platform_enter(void);
>>>>
>>>> +extern char __nosavedata write_speed, read_speed;
>>>>    #else /* !CONFIG_HIBERNATION */
>>>>
>>>>    static inline void hibernate_image_size_init(void) {}
>>>> @@ -161,7 +162,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
>>>>
>>>>    struct timeval;
>>>>    /* kernel/power/swsusp.c */
>>>> -extern void swsusp_show_speed(struct timeval *, struct timeval *,
>>>> +extern int swsusp_show_speed(struct timeval *, struct timeval *,
>>>>    				unsigned int, char *);
>>>>
>>>>    #ifdef CONFIG_SUSPEND
>>>> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
>>>> index 3c01105..caf4db8 100644
>>>> --- a/kernel/power/swap.c
>>>> +++ b/kernel/power/swap.c
>>>> @@ -45,7 +45,8 @@ struct swap_map_page {
>>>>    };
>>>>
>>>>    struct swsusp_header {
>>>> -	char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
>>>> +	char reserved[PAGE_SIZE - 21 - sizeof(sector_t) - sizeof(int)];
>>>> +	char write_speed;
>>>>    	sector_t image;
>>>>    	unsigned int flags;	/* Flags to pass to the "boot" kernel */
>>>>    	char	orig_sig[10];
>>>> @@ -161,6 +162,7 @@ int swsusp_swap_in_use(void)
>>>>
>>>>    static unsigned short root_swap = 0xffff;
>>>>    struct block_device *hib_resume_bdev;
>>>> +char __nosavedata write_speed, read_speed;
>>>
>>> I really should have noticed that earlier, but I don't really like __nosavedata
>>> being used here.  In fact, it shouldn't be used at all any more, because it's
>>> meaningless on x86_64.
>>
>> Really? Okay. When did that change?
>
> Well, some time ago, looks like in 2007, but the files changed and were moving
> around, so it's hard to say exactly.

Hmm. Really failed to notice that one, didn't I? :)

>>> I'm not sure how to implement that without __nosavedata, but please don't
>>> use it.  Sorry aboiut that.
>>
>> Well then, for now, let's drop that patch then. At least it's got us the
>> numbers we needed to see these patches are useful. Longer term, I'll do
>> what I do in TuxOnIce and allocate a page while writing the image, store
>> it's location in the image header and use it the transfer information
>> from the boot kernel to the resumed kernel. (Essentially the same thing,
>> except without the special section).
>
> The problem is that on x86_64 the boot kernel may be completely different
> from the image kernel (different version, different configuration), so there is
> no guarantee that your page frame allocated while writing the image would be
> available to the boot kernel (it may contain the kernel code, for example).
>
> You'd really need to replace one of the image pages with  something prepared
> while the image was being read.  For that, you'd need to allocate a page before
> creating the image and pass its PFN in the image header.

Yes - that's what I'm doing. Maybe that's why the __nosavedata changes 
you mentioned above haven't bitten me.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27 21:05         ` Nigel Cunningham
  2010-09-27 21:16           ` Rafael J. Wysocki
@ 2010-09-27 21:16           ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-09-27 21:16 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Hi.
> 
> On 28/09/10 06:49, Rafael J. Wysocki wrote:
> > On Monday, September 27, 2010, Nigel Cunningham wrote:
...
> >> Well then, for now, let's drop that patch then. At least it's got us the
> >> numbers we needed to see these patches are useful. Longer term, I'll do
> >> what I do in TuxOnIce and allocate a page while writing the image, store
> >> it's location in the image header and use it the transfer information
> >> from the boot kernel to the resumed kernel. (Essentially the same thing,
> >> except without the special section).
> >
> > The problem is that on x86_64 the boot kernel may be completely different
> > from the image kernel (different version, different configuration), so there is
> > no guarantee that your page frame allocated while writing the image would be
> > available to the boot kernel (it may contain the kernel code, for example).
> >
> > You'd really need to replace one of the image pages with  something prepared
> > while the image was being read.  For that, you'd need to allocate a page before
> > creating the image and pass its PFN in the image header.
> 
> Yes - that's what I'm doing. Maybe that's why the __nosavedata changes 
> you mentioned above haven't bitten me.

Well, other than that, the majority of people don't know about that change and
they still use the same kernel for boot/image. :-)

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 02/23] Record & display i/o speed post resume.
  2010-09-27 21:05         ` Nigel Cunningham
@ 2010-09-27 21:16           ` Rafael J. Wysocki
  2010-09-27 21:16           ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-09-27 21:16 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Hi.
> 
> On 28/09/10 06:49, Rafael J. Wysocki wrote:
> > On Monday, September 27, 2010, Nigel Cunningham wrote:
...
> >> Well then, for now, let's drop that patch then. At least it's got us the
> >> numbers we needed to see these patches are useful. Longer term, I'll do
> >> what I do in TuxOnIce and allocate a page while writing the image, store
> >> it's location in the image header and use it the transfer information
> >> from the boot kernel to the resumed kernel. (Essentially the same thing,
> >> except without the special section).
> >
> > The problem is that on x86_64 the boot kernel may be completely different
> > from the image kernel (different version, different configuration), so there is
> > no guarantee that your page frame allocated while writing the image would be
> > available to the boot kernel (it may contain the kernel code, for example).
> >
> > You'd really need to replace one of the image pages with  something prepared
> > while the image was being read.  For that, you'd need to allocate a page before
> > creating the image and pass its PFN in the image header.
> 
> Yes - that's what I'm doing. Maybe that's why the __nosavedata changes 
> you mentioned above haven't bitten me.

Well, other than that, the majority of people don't know about that change and
they still use the same kernel for boot/image. :-)

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-09-27 20:32     ` Nigel Cunningham
  2010-10-01 21:28       ` Rafael J. Wysocki
@ 2010-10-01 21:28       ` Rafael J. Wysocki
  2010-10-01 21:45         ` Nigel Cunningham
  2010-10-01 21:45         ` Nigel Cunningham
  1 sibling, 2 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-10-01 21:28 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Hi.
> 
> On 28/09/10 06:27, Rafael J. Wysocki wrote:
> > On Monday, September 27, 2010, Nigel Cunningham wrote:
...
> > This one doesn't really good to me.  What I'd prefer would be to have a
> > structure of "swap operations" pointers like ->start(), ->write_data(),
> > ->read_data(), and ->finish() that will point to the functions in this file
> > (if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
> > otherwise.  That would reduce the number of the
> > (flags&  SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
> > in code that's easier to follow.
> 
> Me too. I was heading in that direction, but not doing it in one step. 
> I'll happily change that.

I'm still waiting for the reworked patch.  If you can submit it in a few days
and it looks good, I'll include it into the pull request for 2.6.37.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-09-27 20:32     ` Nigel Cunningham
@ 2010-10-01 21:28       ` Rafael J. Wysocki
  2010-10-01 21:28       ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-10-01 21:28 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Monday, September 27, 2010, Nigel Cunningham wrote:
> Hi.
> 
> On 28/09/10 06:27, Rafael J. Wysocki wrote:
> > On Monday, September 27, 2010, Nigel Cunningham wrote:
...
> > This one doesn't really good to me.  What I'd prefer would be to have a
> > structure of "swap operations" pointers like ->start(), ->write_data(),
> > ->read_data(), and ->finish() that will point to the functions in this file
> > (if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
> > otherwise.  That would reduce the number of the
> > (flags&  SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
> > in code that's easier to follow.
> 
> Me too. I was heading in that direction, but not doing it in one step. 
> I'll happily change that.

I'm still waiting for the reworked patch.  If you can submit it in a few days
and it looks good, I'll include it into the pull request for 2.6.37.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-10-01 21:28       ` Rafael J. Wysocki
  2010-10-01 21:45         ` Nigel Cunningham
@ 2010-10-01 21:45         ` Nigel Cunningham
  2010-10-01 22:15           ` Rafael J. Wysocki
  2010-10-01 22:15           ` Rafael J. Wysocki
  1 sibling, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-01 21:45 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi Rafael.

On 02/10/10 07:28, Rafael J. Wysocki wrote:
> On Monday, September 27, 2010, Nigel Cunningham wrote:
>> Hi.
>>
>> On 28/09/10 06:27, Rafael J. Wysocki wrote:
>>> On Monday, September 27, 2010, Nigel Cunningham wrote:
> ...
>>> This one doesn't really good to me.  What I'd prefer would be to have a
>>> structure of "swap operations" pointers like ->start(), ->write_data(),
>>> ->read_data(), and ->finish() that will point to the functions in this file
>>> (if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
>>> otherwise.  That would reduce the number of the
>>> (flags&   SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
>>> in code that's easier to follow.
>>
>> Me too. I was heading in that direction, but not doing it in one step.
>> I'll happily change that.
>
> I'm still waiting for the reworked patch.  If you can submit it in a few days
> and it looks good, I'll include it into the pull request for 2.6.37.

Sorry for the delay.

Would you be happy if, rather than reworking that patch and modifying 
other patches that are affected, I added a new patch to the end of the 
series?

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-10-01 21:28       ` Rafael J. Wysocki
@ 2010-10-01 21:45         ` Nigel Cunningham
  2010-10-01 21:45         ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-01 21:45 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi Rafael.

On 02/10/10 07:28, Rafael J. Wysocki wrote:
> On Monday, September 27, 2010, Nigel Cunningham wrote:
>> Hi.
>>
>> On 28/09/10 06:27, Rafael J. Wysocki wrote:
>>> On Monday, September 27, 2010, Nigel Cunningham wrote:
> ...
>>> This one doesn't really good to me.  What I'd prefer would be to have a
>>> structure of "swap operations" pointers like ->start(), ->write_data(),
>>> ->read_data(), and ->finish() that will point to the functions in this file
>>> (if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
>>> otherwise.  That would reduce the number of the
>>> (flags&   SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
>>> in code that's easier to follow.
>>
>> Me too. I was heading in that direction, but not doing it in one step.
>> I'll happily change that.
>
> I'm still waiting for the reworked patch.  If you can submit it in a few days
> and it looks good, I'll include it into the pull request for 2.6.37.

Sorry for the delay.

Would you be happy if, rather than reworking that patch and modifying 
other patches that are affected, I added a new patch to the end of the 
series?

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-10-01 21:45         ` Nigel Cunningham
  2010-10-01 22:15           ` Rafael J. Wysocki
@ 2010-10-01 22:15           ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-10-01 22:15 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Friday, October 01, 2010, Nigel Cunningham wrote:
> Hi Rafael.

Hi,

> On 02/10/10 07:28, Rafael J. Wysocki wrote:
> > On Monday, September 27, 2010, Nigel Cunningham wrote:
> >> Hi.
> >>
> >> On 28/09/10 06:27, Rafael J. Wysocki wrote:
> >>> On Monday, September 27, 2010, Nigel Cunningham wrote:
> > ...
> >>> This one doesn't really good to me.  What I'd prefer would be to have a
> >>> structure of "swap operations" pointers like ->start(), ->write_data(),
> >>> ->read_data(), and ->finish() that will point to the functions in this file
> >>> (if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
> >>> otherwise.  That would reduce the number of the
> >>> (flags&   SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
> >>> in code that's easier to follow.
> >>
> >> Me too. I was heading in that direction, but not doing it in one step.
> >> I'll happily change that.
> >
> > I'm still waiting for the reworked patch.  If you can submit it in a few days
> > and it looks good, I'll include it into the pull request for 2.6.37.
> 
> Sorry for the delay.

No biggie.

> Would you be happy if, rather than reworking that patch and modifying 
> other patches that are affected, I added a new patch to the end of the 
> series?

Not really.  That would make it difficult for other people to follow the
changes.  Let's do things in the right order from the start. :-)

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 01/23] Hibernation: Split compression support out.
  2010-10-01 21:45         ` Nigel Cunningham
@ 2010-10-01 22:15           ` Rafael J. Wysocki
  2010-10-01 22:15           ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-10-01 22:15 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Friday, October 01, 2010, Nigel Cunningham wrote:
> Hi Rafael.

Hi,

> On 02/10/10 07:28, Rafael J. Wysocki wrote:
> > On Monday, September 27, 2010, Nigel Cunningham wrote:
> >> Hi.
> >>
> >> On 28/09/10 06:27, Rafael J. Wysocki wrote:
> >>> On Monday, September 27, 2010, Nigel Cunningham wrote:
> > ...
> >>> This one doesn't really good to me.  What I'd prefer would be to have a
> >>> structure of "swap operations" pointers like ->start(), ->write_data(),
> >>> ->read_data(), and ->finish() that will point to the functions in this file
> >>> (if compression is to be used) or to the "old" swap_write_page()/swap_read_page()
> >>> otherwise.  That would reduce the number of the
> >>> (flags&   SF_NOCOMPRESS_MODE) checks quite substantially and will likely result
> >>> in code that's easier to follow.
> >>
> >> Me too. I was heading in that direction, but not doing it in one step.
> >> I'll happily change that.
> >
> > I'm still waiting for the reworked patch.  If you can submit it in a few days
> > and it looks good, I'll include it into the pull request for 2.6.37.
> 
> Sorry for the delay.

No biggie.

> Would you be happy if, rather than reworking that patch and modifying 
> other patches that are affected, I added a new patch to the end of the 
> series?

Not really.  That would make it difficult for other people to follow the
changes.  Let's do things in the right order from the start. :-)

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (52 preceding siblings ...)
  2010-10-02 16:49 ` Martin Steigerwald
@ 2010-10-02 16:49 ` Martin Steigerwald
  2010-10-04  8:00   ` Martin Steigerwald
  2010-10-04  8:00   ` [linux-pm] " Martin Steigerwald
  53 siblings, 2 replies; 113+ messages in thread
From: Martin Steigerwald @ 2010-10-02 16:49 UTC (permalink / raw)
  To: linux-pm; +Cc: Nigel Cunningham, Rafael J. Wysocki, LKML, TuxOnIce-devel

[-- Attachment #1: Type: Text/Plain, Size: 3332 bytes --]

Am Montag 27 September 2010 schrieb Nigel Cunningham:
> Hi again Rafael.

Hi Nigel and Rafael,

> As discussed, here are the patches, modified to apply against your
> current linux-next tree. A new first patch splits compression support
> out into its own file, removing the need to have two versions of the
> load_image and save_image routines, minimising the changes to the
> remainder of the patches and making things cleaner than would
> otherwise be the case.
> 
> On my laptop, single-threaded compression actually slows writing down
> from 175MB/s to around 100-120MB/s (depending on how well the image
> compresses). Reading speed improves from 218MB/s to around 245MB/s. I
> expect that multithreaded writing would bring the writing (and
> reading) speeds back up. It's on my swsusp to do list :)

Testing this now (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069-
dirty).

So far so fast:

shambhala:~> grep Image /var/log/syslog | tail -30
Sep 29 09:11:07 shambhala kernel: PM: Image restored successfully.
Sep 29 09:11:07 shambhala kernel: PM: Image written at 47 MB/s.
Sep 29 09:11:07 shambhala kernel: PM: Image read at 45 MB/s.
Sep 29 20:59:32 shambhala kernel: PM: Image restored successfully.
Sep 29 20:59:32 shambhala kernel: PM: Image written at 42 MB/s.
Sep 29 20:59:32 shambhala kernel: PM: Image read at 43 MB/s.
Sep 30 19:17:57 shambhala kernel: PM: Image restored successfully.
Sep 30 19:17:57 shambhala kernel: PM: Image written at 62 MB/s.
Sep 30 19:17:57 shambhala kernel: PM: Image read at 42 MB/s.
Oct  1 11:26:19 shambhala kernel: PM: Image restored successfully.
Oct  1 11:26:19 shambhala kernel: PM: Image written at 18 MB/s.
Oct  1 11:26:19 shambhala kernel: PM: Image read at 45 MB/s.
Oct  2 10:30:24 shambhala kernel: PM: Image restored successfully.
Oct  2 10:30:24 shambhala kernel: PM: Image written at 65 MB/s.
Oct  2 10:30:24 shambhala kernel: PM: Image read at 42 MB/s.
Oct  2 17:44:33 shambhala kernel: PM: Image restored successfully.
Oct  2 17:44:33 shambhala kernel: PM: Image written at 74 MB/s.
Oct  2 17:44:33 shambhala kernel: PM: Image read at 116 MB/s.
Oct  2 17:56:18 shambhala kernel: PM: Image restored successfully.
Oct  2 17:56:18 shambhala kernel: PM: Image written at 68 MB/s.
Oct  2 17:56:18 shambhala kernel: PM: Image read at 125 MB/s.
Oct  2 17:57:40 shambhala kernel: PM: Image restored successfully.
Oct  2 17:57:40 shambhala kernel: PM: Image written at 67 MB/s.
Oct  2 17:57:40 shambhala kernel: PM: Image read at 121 MB/s.
Oct  2 17:58:47 shambhala kernel: PM: Image restored successfully.
Oct  2 17:58:47 shambhala kernel: PM: Image written at 67 MB/s.
Oct  2 17:58:47 shambhala kernel: PM: Image read at 124 MB/s.
Oct  2 18:43:40 shambhala kernel: PM: Image restored successfully.
Oct  2 18:43:40 shambhala kernel: PM: Image written at 68 MB/s.
Oct  2 18:43:40 shambhala kernel: PM: Image read at 122 MB/s.
shambhala:~>

The read ahead patches bring a pretty nice performance upgrade ;).

I wonder a bit about:

Oct  1 11:26:19 shambhala kernel: PM: Image written at 18 MB/s.

This has been without read ahead patches which shouldn't interfere with 
writing anyway.

Ciao,
-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: Swsusp patches applied to suspend-2.6#linux-next
  2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
                   ` (51 preceding siblings ...)
  2010-09-27  8:00 ` Andrey Rahmatullin
@ 2010-10-02 16:49 ` Martin Steigerwald
  2010-10-02 16:49 ` [linux-pm] " Martin Steigerwald
  53 siblings, 0 replies; 113+ messages in thread
From: Martin Steigerwald @ 2010-10-02 16:49 UTC (permalink / raw)
  To: linux-pm; +Cc: LKML, TuxOnIce-devel


[-- Attachment #1.1: Type: Text/Plain, Size: 3332 bytes --]

Am Montag 27 September 2010 schrieb Nigel Cunningham:
> Hi again Rafael.

Hi Nigel and Rafael,

> As discussed, here are the patches, modified to apply against your
> current linux-next tree. A new first patch splits compression support
> out into its own file, removing the need to have two versions of the
> load_image and save_image routines, minimising the changes to the
> remainder of the patches and making things cleaner than would
> otherwise be the case.
> 
> On my laptop, single-threaded compression actually slows writing down
> from 175MB/s to around 100-120MB/s (depending on how well the image
> compresses). Reading speed improves from 218MB/s to around 245MB/s. I
> expect that multithreaded writing would bring the writing (and
> reading) speeds back up. It's on my swsusp to do list :)

Testing this now (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069-
dirty).

So far so fast:

shambhala:~> grep Image /var/log/syslog | tail -30
Sep 29 09:11:07 shambhala kernel: PM: Image restored successfully.
Sep 29 09:11:07 shambhala kernel: PM: Image written at 47 MB/s.
Sep 29 09:11:07 shambhala kernel: PM: Image read at 45 MB/s.
Sep 29 20:59:32 shambhala kernel: PM: Image restored successfully.
Sep 29 20:59:32 shambhala kernel: PM: Image written at 42 MB/s.
Sep 29 20:59:32 shambhala kernel: PM: Image read at 43 MB/s.
Sep 30 19:17:57 shambhala kernel: PM: Image restored successfully.
Sep 30 19:17:57 shambhala kernel: PM: Image written at 62 MB/s.
Sep 30 19:17:57 shambhala kernel: PM: Image read at 42 MB/s.
Oct  1 11:26:19 shambhala kernel: PM: Image restored successfully.
Oct  1 11:26:19 shambhala kernel: PM: Image written at 18 MB/s.
Oct  1 11:26:19 shambhala kernel: PM: Image read at 45 MB/s.
Oct  2 10:30:24 shambhala kernel: PM: Image restored successfully.
Oct  2 10:30:24 shambhala kernel: PM: Image written at 65 MB/s.
Oct  2 10:30:24 shambhala kernel: PM: Image read at 42 MB/s.
Oct  2 17:44:33 shambhala kernel: PM: Image restored successfully.
Oct  2 17:44:33 shambhala kernel: PM: Image written at 74 MB/s.
Oct  2 17:44:33 shambhala kernel: PM: Image read at 116 MB/s.
Oct  2 17:56:18 shambhala kernel: PM: Image restored successfully.
Oct  2 17:56:18 shambhala kernel: PM: Image written at 68 MB/s.
Oct  2 17:56:18 shambhala kernel: PM: Image read at 125 MB/s.
Oct  2 17:57:40 shambhala kernel: PM: Image restored successfully.
Oct  2 17:57:40 shambhala kernel: PM: Image written at 67 MB/s.
Oct  2 17:57:40 shambhala kernel: PM: Image read at 121 MB/s.
Oct  2 17:58:47 shambhala kernel: PM: Image restored successfully.
Oct  2 17:58:47 shambhala kernel: PM: Image written at 67 MB/s.
Oct  2 17:58:47 shambhala kernel: PM: Image read at 124 MB/s.
Oct  2 18:43:40 shambhala kernel: PM: Image restored successfully.
Oct  2 18:43:40 shambhala kernel: PM: Image written at 68 MB/s.
Oct  2 18:43:40 shambhala kernel: PM: Image read at 122 MB/s.
shambhala:~>

The read ahead patches bring a pretty nice performance upgrade ;).

I wonder a bit about:

Oct  1 11:26:19 shambhala kernel: PM: Image written at 18 MB/s.

This has been without read ahead patches which shouldn't interfere with 
writing anyway.

Ciao,
-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] Swsusp patches applied to suspend-2.6#linux-next
  2010-10-02 16:49 ` [linux-pm] " Martin Steigerwald
  2010-10-04  8:00   ` Martin Steigerwald
@ 2010-10-04  8:00   ` Martin Steigerwald
  2010-10-04  8:31     ` Nigel Cunningham
                       ` (3 more replies)
  1 sibling, 4 replies; 113+ messages in thread
From: Martin Steigerwald @ 2010-10-04  8:00 UTC (permalink / raw)
  To: linux-pm; +Cc: LKML, TuxOnIce-devel, Nigel Cunningham, Rafael J. Wysocki

[-- Attachment #1: Type: Text/Plain, Size: 4248 bytes --]

Am Samstag 02 Oktober 2010 schrieb Martin Steigerwald:
> Am Montag 27 September 2010 schrieb Nigel Cunningham:
> > Hi again Rafael.
> 
> Hi Nigel and Rafael,
> 
> > As discussed, here are the patches, modified to apply against your
> > current linux-next tree. A new first patch splits compression support
> > out into its own file, removing the need to have two versions of the
> > load_image and save_image routines, minimising the changes to the
> > remainder of the patches and making things cleaner than would
> > otherwise be the case.
> > 
> > On my laptop, single-threaded compression actually slows writing down
> > from 175MB/s to around 100-120MB/s (depending on how well the image
> > compresses). Reading speed improves from 218MB/s to around 245MB/s. I
> > expect that multithreaded writing would bring the writing (and
> > reading) speeds back up. It's on my swsusp to do list :)
> 
> Testing this now
> (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069- dirty).

Two times I had the rather strange issue that the machine booted freshly 
instead of resuming! First I thought I maybe didn't wait until the image 
was saved, before turning the laptop off. But now it happened a second time 
and also the ThinkPad T42 has a battery in it, thus it should always be 
able to complete writing the image.

For resuming I found this in the syslog:

Oct  4 09:19:10 shambhala kernel: end_request: I/O error, dev fd0, sector 
0
Oct  4 09:19:10 shambhala kernel: PM: Starting manual resume from disk
Oct  4 09:19:10 shambhala kernel: PM: Resume from partition 8:2
Oct  4 09:19:10 shambhala kernel: PM: Checking hibernation image.
Oct  4 09:19:10 shambhala kernel: PM: Error -22 checking image file
Oct  4 09:19:10 shambhala kernel: PM: Resume from disk failed.
Oct  4 09:19:10 shambhala kernel: PM: Marking nosave pages: 
000000000009f000 - 0000000000100000
Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps created
Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps freed

What does error -22 mean?

For hibernating:

Oct  4 00:13:09 shambhala ifplugd(eth0)[15127]: Link beat lost.
Oct  4 00:13:10 shambhala NetworkManager[2146]: <info> (eth0): carrier now 
OFF (device state 1)
Oct  4 00:13:12 shambhala ifplugd(eth0)[15127]: Exiting.
Oct  4 00:13:14 shambhala postfix/master[2589]: reload -- version 2.7.1, 
configuration /etc/postfix
Oct  4 00:13:14 shambhala dhclient: Internet Systems Consortium DHCP 
Client 4.1.1-P1
Oct  4 00:13:14 shambhala dhclient: Copyright 2004-2010 Internet Systems 
Consortium.
Oct  4 00:13:14 shambhala dhclient: All rights reserved.
Oct  4 00:13:14 shambhala dhclient: For info, please visit 
https://www.isc.org/software/dhcp/
Oct  4 00:13:14 shambhala dhclient: 
Oct  4 00:13:14 shambhala dhclient: Listening on 
LPF/eth0/00:11:25:46:ec:a5
Oct  4 00:13:14 shambhala dhclient: Sending on   
LPF/eth0/00:11:25:46:ec:a5
Oct  4 00:13:14 shambhala dhclient: Sending on   Socket/fallback
Oct  4 00:13:15 shambhala dhclient: DHCPRELEASE on eth0 to 10.0.0.9 port 
67
Oct  4 00:13:18 shambhala kernel: PM: Marking nosave pages: 
000000000009f000 - 0000000000100000
Oct  4 00:13:18 shambhala kernel: PM: Basic memory bitmaps created
Oct  4 00:13:18 shambhala kernel: PM: Syncing filesystems ... done.
Oct  4 09:19:10 shambhala kernel: imklog 4.6.4, log source = /proc/kmsg 
started.
Oct  4 09:19:10 shambhala rsyslogd: [origin software="rsyslogd" 
swVersion="4.6.4" x-pid="1964" x-info="http://www.rsyslog.com"] (re)start
Oct  4 09:19:10 shambhala kernel: r hub
Oct  4 09:19:10 shambhala kernel: usbcore: registered new device driver 
usb

Which is not complete. It seems the last log messages prior to hibernating 
have not fully been written by rsyslog.

Whats going on there? I didn't see this with Nigel's patches without the 
readahead patch. But then now I am testing suspend next + his patches, 
which may well contain other patches, as far as I understand.

Any change to test with some newer state of suspend-next?

Rafael did you integrate Nigel's patches in your tree?

Ciao,
-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: Swsusp patches applied to suspend-2.6#linux-next
  2010-10-02 16:49 ` [linux-pm] " Martin Steigerwald
@ 2010-10-04  8:00   ` Martin Steigerwald
  2010-10-04  8:00   ` [linux-pm] " Martin Steigerwald
  1 sibling, 0 replies; 113+ messages in thread
From: Martin Steigerwald @ 2010-10-04  8:00 UTC (permalink / raw)
  To: linux-pm; +Cc: Nigel Cunningham, LKML, TuxOnIce-devel


[-- Attachment #1.1: Type: Text/Plain, Size: 4248 bytes --]

Am Samstag 02 Oktober 2010 schrieb Martin Steigerwald:
> Am Montag 27 September 2010 schrieb Nigel Cunningham:
> > Hi again Rafael.
> 
> Hi Nigel and Rafael,
> 
> > As discussed, here are the patches, modified to apply against your
> > current linux-next tree. A new first patch splits compression support
> > out into its own file, removing the need to have two versions of the
> > load_image and save_image routines, minimising the changes to the
> > remainder of the patches and making things cleaner than would
> > otherwise be the case.
> > 
> > On my laptop, single-threaded compression actually slows writing down
> > from 175MB/s to around 100-120MB/s (depending on how well the image
> > compresses). Reading speed improves from 218MB/s to around 245MB/s. I
> > expect that multithreaded writing would bring the writing (and
> > reading) speeds back up. It's on my swsusp to do list :)
> 
> Testing this now
> (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069- dirty).

Two times I had the rather strange issue that the machine booted freshly 
instead of resuming! First I thought I maybe didn't wait until the image 
was saved, before turning the laptop off. But now it happened a second time 
and also the ThinkPad T42 has a battery in it, thus it should always be 
able to complete writing the image.

For resuming I found this in the syslog:

Oct  4 09:19:10 shambhala kernel: end_request: I/O error, dev fd0, sector 
0
Oct  4 09:19:10 shambhala kernel: PM: Starting manual resume from disk
Oct  4 09:19:10 shambhala kernel: PM: Resume from partition 8:2
Oct  4 09:19:10 shambhala kernel: PM: Checking hibernation image.
Oct  4 09:19:10 shambhala kernel: PM: Error -22 checking image file
Oct  4 09:19:10 shambhala kernel: PM: Resume from disk failed.
Oct  4 09:19:10 shambhala kernel: PM: Marking nosave pages: 
000000000009f000 - 0000000000100000
Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps created
Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps freed

What does error -22 mean?

For hibernating:

Oct  4 00:13:09 shambhala ifplugd(eth0)[15127]: Link beat lost.
Oct  4 00:13:10 shambhala NetworkManager[2146]: <info> (eth0): carrier now 
OFF (device state 1)
Oct  4 00:13:12 shambhala ifplugd(eth0)[15127]: Exiting.
Oct  4 00:13:14 shambhala postfix/master[2589]: reload -- version 2.7.1, 
configuration /etc/postfix
Oct  4 00:13:14 shambhala dhclient: Internet Systems Consortium DHCP 
Client 4.1.1-P1
Oct  4 00:13:14 shambhala dhclient: Copyright 2004-2010 Internet Systems 
Consortium.
Oct  4 00:13:14 shambhala dhclient: All rights reserved.
Oct  4 00:13:14 shambhala dhclient: For info, please visit 
https://www.isc.org/software/dhcp/
Oct  4 00:13:14 shambhala dhclient: 
Oct  4 00:13:14 shambhala dhclient: Listening on 
LPF/eth0/00:11:25:46:ec:a5
Oct  4 00:13:14 shambhala dhclient: Sending on   
LPF/eth0/00:11:25:46:ec:a5
Oct  4 00:13:14 shambhala dhclient: Sending on   Socket/fallback
Oct  4 00:13:15 shambhala dhclient: DHCPRELEASE on eth0 to 10.0.0.9 port 
67
Oct  4 00:13:18 shambhala kernel: PM: Marking nosave pages: 
000000000009f000 - 0000000000100000
Oct  4 00:13:18 shambhala kernel: PM: Basic memory bitmaps created
Oct  4 00:13:18 shambhala kernel: PM: Syncing filesystems ... done.
Oct  4 09:19:10 shambhala kernel: imklog 4.6.4, log source = /proc/kmsg 
started.
Oct  4 09:19:10 shambhala rsyslogd: [origin software="rsyslogd" 
swVersion="4.6.4" x-pid="1964" x-info="http://www.rsyslog.com"] (re)start
Oct  4 09:19:10 shambhala kernel: r hub
Oct  4 09:19:10 shambhala kernel: usbcore: registered new device driver 
usb

Which is not complete. It seems the last log messages prior to hibernating 
have not fully been written by rsyslog.

Whats going on there? I didn't see this with Nigel's patches without the 
readahead patch. But then now I am testing suspend next + his patches, 
which may well contain other patches, as far as I understand.

Any change to test with some newer state of suspend-next?

Rafael did you integrate Nigel's patches in your tree?

Ciao,
-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] Swsusp patches applied to suspend-2.6#linux-next
  2010-10-04  8:00   ` [linux-pm] " Martin Steigerwald
  2010-10-04  8:31     ` Nigel Cunningham
@ 2010-10-04  8:31     ` Nigel Cunningham
  2010-10-04  8:55       ` Martin Steigerwald
  2010-10-04  8:55       ` Martin Steigerwald
  2010-10-04  8:47     ` Martin Steigerwald
  2010-10-04  8:47     ` [linux-pm] " Martin Steigerwald
  3 siblings, 2 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-04  8:31 UTC (permalink / raw)
  To: Martin Steigerwald; +Cc: linux-pm, Nigel Cunningham, LKML, TuxOnIce-devel

Hi Martin.

On 04/10/10 19:00, Martin Steigerwald wrote:
> Am Samstag 02 Oktober 2010 schrieb Martin Steigerwald:
>> Am Montag 27 September 2010 schrieb Nigel Cunningham:
>>> Hi again Rafael.
>>
>> Hi Nigel and Rafael,
>>
>>> As discussed, here are the patches, modified to apply against your
>>> current linux-next tree. A new first patch splits compression support
>>> out into its own file, removing the need to have two versions of the
>>> load_image and save_image routines, minimising the changes to the
>>> remainder of the patches and making things cleaner than would
>>> otherwise be the case.
>>>
>>> On my laptop, single-threaded compression actually slows writing down
>>> from 175MB/s to around 100-120MB/s (depending on how well the image
>>> compresses). Reading speed improves from 218MB/s to around 245MB/s. I
>>> expect that multithreaded writing would bring the writing (and
>>> reading) speeds back up. It's on my swsusp to do list :)
>>
>> Testing this now
>> (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069- dirty).
>
> Two times I had the rather strange issue that the machine booted freshly
> instead of resuming! First I thought I maybe didn't wait until the image
> was saved, before turning the laptop off. But now it happened a second time
> and also the ThinkPad T42 has a battery in it, thus it should always be
> able to complete writing the image.
>
> For resuming I found this in the syslog:
>
> Oct  4 09:19:10 shambhala kernel: end_request: I/O error, dev fd0, sector
> 0
> Oct  4 09:19:10 shambhala kernel: PM: Starting manual resume from disk
> Oct  4 09:19:10 shambhala kernel: PM: Resume from partition 8:2
> Oct  4 09:19:10 shambhala kernel: PM: Checking hibernation image.
> Oct  4 09:19:10 shambhala kernel: PM: Error -22 checking image file
> Oct  4 09:19:10 shambhala kernel: PM: Resume from disk failed.
> Oct  4 09:19:10 shambhala kernel: PM: Marking nosave pages:
> 000000000009f000 - 0000000000100000
> Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps created
> Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps freed
>
> What does error -22 mean?

-22 is -EINVAL. There are a few reasons that it could occur, but rather 
than chasing our tails, how about if I just tell you that I've been 
working on a new version of the patches that will provide more detailed 
debugging of issues like this (printks that can be enabled/disabled at 
run time) - and hopefully address your issue so it won't happen anyway.

> For hibernating:
>
> Oct  4 00:13:09 shambhala ifplugd(eth0)[15127]: Link beat lost.
> Oct  4 00:13:10 shambhala NetworkManager[2146]:<info>  (eth0): carrier now
> OFF (device state 1)
> Oct  4 00:13:12 shambhala ifplugd(eth0)[15127]: Exiting.
> Oct  4 00:13:14 shambhala postfix/master[2589]: reload -- version 2.7.1,
> configuration /etc/postfix
> Oct  4 00:13:14 shambhala dhclient: Internet Systems Consortium DHCP
> Client 4.1.1-P1
> Oct  4 00:13:14 shambhala dhclient: Copyright 2004-2010 Internet Systems
> Consortium.
> Oct  4 00:13:14 shambhala dhclient: All rights reserved.
> Oct  4 00:13:14 shambhala dhclient: For info, please visit
> https://www.isc.org/software/dhcp/
> Oct  4 00:13:14 shambhala dhclient:
> Oct  4 00:13:14 shambhala dhclient: Listening on
> LPF/eth0/00:11:25:46:ec:a5
> Oct  4 00:13:14 shambhala dhclient: Sending on
> LPF/eth0/00:11:25:46:ec:a5
> Oct  4 00:13:14 shambhala dhclient: Sending on   Socket/fallback
> Oct  4 00:13:15 shambhala dhclient: DHCPRELEASE on eth0 to 10.0.0.9 port
> 67
> Oct  4 00:13:18 shambhala kernel: PM: Marking nosave pages:
> 000000000009f000 - 0000000000100000
> Oct  4 00:13:18 shambhala kernel: PM: Basic memory bitmaps created
> Oct  4 00:13:18 shambhala kernel: PM: Syncing filesystems ... done.
> Oct  4 09:19:10 shambhala kernel: imklog 4.6.4, log source = /proc/kmsg
> started.
> Oct  4 09:19:10 shambhala rsyslogd: [origin software="rsyslogd"
> swVersion="4.6.4" x-pid="1964" x-info="http://www.rsyslog.com"] (re)start
> Oct  4 09:19:10 shambhala kernel: r hub
> Oct  4 09:19:10 shambhala kernel: usbcore: registered new device driver
> usb
>
> Which is not complete. It seems the last log messages prior to hibernating
> have not fully been written by rsyslog.

That's not unusual - after we do the atomic copy, nothing gets logged.

> Whats going on there? I didn't see this with Nigel's patches without the
> readahead patch. But then now I am testing suspend next + his patches,
> which may well contain other patches, as far as I understand.
>
> Any change to test with some newer state of suspend-next?
>
> Rafael did you integrate Nigel's patches in your tree?

We agreed not to yet - I'm splitting the compression support out 
properly, and will then post another version.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: Swsusp patches applied to suspend-2.6#linux-next
  2010-10-04  8:00   ` [linux-pm] " Martin Steigerwald
@ 2010-10-04  8:31     ` Nigel Cunningham
  2010-10-04  8:31     ` [linux-pm] " Nigel Cunningham
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-04  8:31 UTC (permalink / raw)
  To: Martin Steigerwald; +Cc: TuxOnIce-devel, linux-pm, Nigel Cunningham, LKML

Hi Martin.

On 04/10/10 19:00, Martin Steigerwald wrote:
> Am Samstag 02 Oktober 2010 schrieb Martin Steigerwald:
>> Am Montag 27 September 2010 schrieb Nigel Cunningham:
>>> Hi again Rafael.
>>
>> Hi Nigel and Rafael,
>>
>>> As discussed, here are the patches, modified to apply against your
>>> current linux-next tree. A new first patch splits compression support
>>> out into its own file, removing the need to have two versions of the
>>> load_image and save_image routines, minimising the changes to the
>>> remainder of the patches and making things cleaner than would
>>> otherwise be the case.
>>>
>>> On my laptop, single-threaded compression actually slows writing down
>>> from 175MB/s to around 100-120MB/s (depending on how well the image
>>> compresses). Reading speed improves from 218MB/s to around 245MB/s. I
>>> expect that multithreaded writing would bring the writing (and
>>> reading) speeds back up. It's on my swsusp to do list :)
>>
>> Testing this now
>> (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069- dirty).
>
> Two times I had the rather strange issue that the machine booted freshly
> instead of resuming! First I thought I maybe didn't wait until the image
> was saved, before turning the laptop off. But now it happened a second time
> and also the ThinkPad T42 has a battery in it, thus it should always be
> able to complete writing the image.
>
> For resuming I found this in the syslog:
>
> Oct  4 09:19:10 shambhala kernel: end_request: I/O error, dev fd0, sector
> 0
> Oct  4 09:19:10 shambhala kernel: PM: Starting manual resume from disk
> Oct  4 09:19:10 shambhala kernel: PM: Resume from partition 8:2
> Oct  4 09:19:10 shambhala kernel: PM: Checking hibernation image.
> Oct  4 09:19:10 shambhala kernel: PM: Error -22 checking image file
> Oct  4 09:19:10 shambhala kernel: PM: Resume from disk failed.
> Oct  4 09:19:10 shambhala kernel: PM: Marking nosave pages:
> 000000000009f000 - 0000000000100000
> Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps created
> Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps freed
>
> What does error -22 mean?

-22 is -EINVAL. There are a few reasons that it could occur, but rather 
than chasing our tails, how about if I just tell you that I've been 
working on a new version of the patches that will provide more detailed 
debugging of issues like this (printks that can be enabled/disabled at 
run time) - and hopefully address your issue so it won't happen anyway.

> For hibernating:
>
> Oct  4 00:13:09 shambhala ifplugd(eth0)[15127]: Link beat lost.
> Oct  4 00:13:10 shambhala NetworkManager[2146]:<info>  (eth0): carrier now
> OFF (device state 1)
> Oct  4 00:13:12 shambhala ifplugd(eth0)[15127]: Exiting.
> Oct  4 00:13:14 shambhala postfix/master[2589]: reload -- version 2.7.1,
> configuration /etc/postfix
> Oct  4 00:13:14 shambhala dhclient: Internet Systems Consortium DHCP
> Client 4.1.1-P1
> Oct  4 00:13:14 shambhala dhclient: Copyright 2004-2010 Internet Systems
> Consortium.
> Oct  4 00:13:14 shambhala dhclient: All rights reserved.
> Oct  4 00:13:14 shambhala dhclient: For info, please visit
> https://www.isc.org/software/dhcp/
> Oct  4 00:13:14 shambhala dhclient:
> Oct  4 00:13:14 shambhala dhclient: Listening on
> LPF/eth0/00:11:25:46:ec:a5
> Oct  4 00:13:14 shambhala dhclient: Sending on
> LPF/eth0/00:11:25:46:ec:a5
> Oct  4 00:13:14 shambhala dhclient: Sending on   Socket/fallback
> Oct  4 00:13:15 shambhala dhclient: DHCPRELEASE on eth0 to 10.0.0.9 port
> 67
> Oct  4 00:13:18 shambhala kernel: PM: Marking nosave pages:
> 000000000009f000 - 0000000000100000
> Oct  4 00:13:18 shambhala kernel: PM: Basic memory bitmaps created
> Oct  4 00:13:18 shambhala kernel: PM: Syncing filesystems ... done.
> Oct  4 09:19:10 shambhala kernel: imklog 4.6.4, log source = /proc/kmsg
> started.
> Oct  4 09:19:10 shambhala rsyslogd: [origin software="rsyslogd"
> swVersion="4.6.4" x-pid="1964" x-info="http://www.rsyslog.com"] (re)start
> Oct  4 09:19:10 shambhala kernel: r hub
> Oct  4 09:19:10 shambhala kernel: usbcore: registered new device driver
> usb
>
> Which is not complete. It seems the last log messages prior to hibernating
> have not fully been written by rsyslog.

That's not unusual - after we do the atomic copy, nothing gets logged.

> Whats going on there? I didn't see this with Nigel's patches without the
> readahead patch. But then now I am testing suspend next + his patches,
> which may well contain other patches, as far as I understand.
>
> Any change to test with some newer state of suspend-next?
>
> Rafael did you integrate Nigel's patches in your tree?

We agreed not to yet - I'm splitting the compression support out 
properly, and will then post another version.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] Swsusp patches applied to suspend-2.6#linux-next
  2010-10-04  8:00   ` [linux-pm] " Martin Steigerwald
                       ` (2 preceding siblings ...)
  2010-10-04  8:47     ` Martin Steigerwald
@ 2010-10-04  8:47     ` Martin Steigerwald
  3 siblings, 0 replies; 113+ messages in thread
From: Martin Steigerwald @ 2010-10-04  8:47 UTC (permalink / raw)
  To: linux-pm; +Cc: Nigel Cunningham, LKML, TuxOnIce-devel, Rafael J. Wysocki

[-- Attachment #1: Type: Text/Plain, Size: 5217 bytes --]

Am Montag 04 Oktober 2010 schrieb Martin Steigerwald:
> Am Samstag 02 Oktober 2010 schrieb Martin Steigerwald:
> > Am Montag 27 September 2010 schrieb Nigel Cunningham:
> > > Hi again Rafael.
> > 
> > Hi Nigel and Rafael,
> > 
> > > As discussed, here are the patches, modified to apply against your
> > > current linux-next tree. A new first patch splits compression
> > > support out into its own file, removing the need to have two
> > > versions of the load_image and save_image routines, minimising the
> > > changes to the remainder of the patches and making things cleaner
> > > than would otherwise be the case.
> > > 
> > > On my laptop, single-threaded compression actually slows writing
> > > down from 175MB/s to around 100-120MB/s (depending on how well the
> > > image compresses). Reading speed improves from 218MB/s to around
> > > 245MB/s. I expect that multithreaded writing would bring the
> > > writing (and reading) speeds back up. It's on my swsusp to do list
> > > :)
> > 
> > Testing this now
> > (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069- dirty).
> 
> Two times I had the rather strange issue that the machine booted
> freshly instead of resuming! First I thought I maybe didn't wait until
> the image was saved, before turning the laptop off. But now it
> happened a second time and also the ThinkPad T42 has a battery in it,
> thus it should always be able to complete writing the image.
> 
> For resuming I found this in the syslog:
> 
> Oct  4 09:19:10 shambhala kernel: end_request: I/O error, dev fd0,
> sector 0
> Oct  4 09:19:10 shambhala kernel: PM: Starting manual resume from disk
> Oct  4 09:19:10 shambhala kernel: PM: Resume from partition 8:2
> Oct  4 09:19:10 shambhala kernel: PM: Checking hibernation image.
> Oct  4 09:19:10 shambhala kernel: PM: Error -22 checking image file
> Oct  4 09:19:10 shambhala kernel: PM: Resume from disk failed.
> Oct  4 09:19:10 shambhala kernel: PM: Marking nosave pages:
> 000000000009f000 - 0000000000100000
> Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps created
> Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps freed
> 
> What does error -22 mean?
> 
> For hibernating:
> 
> Oct  4 00:13:09 shambhala ifplugd(eth0)[15127]: Link beat lost.
> Oct  4 00:13:10 shambhala NetworkManager[2146]: <info> (eth0): carrier
> now OFF (device state 1)
> Oct  4 00:13:12 shambhala ifplugd(eth0)[15127]: Exiting.
> Oct  4 00:13:14 shambhala postfix/master[2589]: reload -- version
> 2.7.1, configuration /etc/postfix
> Oct  4 00:13:14 shambhala dhclient: Internet Systems Consortium DHCP
> Client 4.1.1-P1
> Oct  4 00:13:14 shambhala dhclient: Copyright 2004-2010 Internet
> Systems Consortium.
> Oct  4 00:13:14 shambhala dhclient: All rights reserved.
> Oct  4 00:13:14 shambhala dhclient: For info, please visit
> https://www.isc.org/software/dhcp/
> Oct  4 00:13:14 shambhala dhclient:
> Oct  4 00:13:14 shambhala dhclient: Listening on
> LPF/eth0/00:11:25:46:ec:a5
> Oct  4 00:13:14 shambhala dhclient: Sending on
> LPF/eth0/00:11:25:46:ec:a5
> Oct  4 00:13:14 shambhala dhclient: Sending on   Socket/fallback
> Oct  4 00:13:15 shambhala dhclient: DHCPRELEASE on eth0 to 10.0.0.9
> port 67
> Oct  4 00:13:18 shambhala kernel: PM: Marking nosave pages:
> 000000000009f000 - 0000000000100000
> Oct  4 00:13:18 shambhala kernel: PM: Basic memory bitmaps created
> Oct  4 00:13:18 shambhala kernel: PM: Syncing filesystems ... done.
> Oct  4 09:19:10 shambhala kernel: imklog 4.6.4, log source = /proc/kmsg
> started.
> Oct  4 09:19:10 shambhala rsyslogd: [origin software="rsyslogd"
> swVersion="4.6.4" x-pid="1964" x-info="http://www.rsyslog.com"]
> (re)start Oct  4 09:19:10 shambhala kernel: r hub
> Oct  4 09:19:10 shambhala kernel: usbcore: registered new device driver
> usb
> 
> Which is not complete. It seems the last log messages prior to
> hibernating have not fully been written by rsyslog.
> 
> Whats going on there? I didn't see this with Nigel's patches without
> the readahead patch. But then now I am testing suspend next + his
> patches, which may well contain other patches, as far as I understand.
> 
> Any change to test with some newer state of suspend-next?
> 
> Rafael did you integrate Nigel's patches in your tree?

Hmmm, there might be a similarity  between these:

In both times it happened after I made at least one suspend to ram cycle. 
Yesterday I plugged the laptop to my hi-fi and forget to switch on the 
power extension lead. Thus KDE's Power management suspended to RAM after 
15 minutes of inactivity.

So maybe suspend to RAM interferes somehow.

Additionally I tend to get Radeon DRM KMS graphics corruption with that 
kernel. And even a complete lockup once.

I think I will try 2.6.35-rc5 or whatever is latest with Nigel's patches 
from Nigel's for-rafael branch in order to isolate whether what I see is 
an issue with Nigel's patches or with any of the other stuff in suspend-
next.

Unless to have some newer stuff for me to test with.

-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: Swsusp patches applied to suspend-2.6#linux-next
  2010-10-04  8:00   ` [linux-pm] " Martin Steigerwald
  2010-10-04  8:31     ` Nigel Cunningham
  2010-10-04  8:31     ` [linux-pm] " Nigel Cunningham
@ 2010-10-04  8:47     ` Martin Steigerwald
  2010-10-04  8:47     ` [linux-pm] " Martin Steigerwald
  3 siblings, 0 replies; 113+ messages in thread
From: Martin Steigerwald @ 2010-10-04  8:47 UTC (permalink / raw)
  To: linux-pm; +Cc: TuxOnIce-devel, Nigel Cunningham, LKML


[-- Attachment #1.1: Type: Text/Plain, Size: 5217 bytes --]

Am Montag 04 Oktober 2010 schrieb Martin Steigerwald:
> Am Samstag 02 Oktober 2010 schrieb Martin Steigerwald:
> > Am Montag 27 September 2010 schrieb Nigel Cunningham:
> > > Hi again Rafael.
> > 
> > Hi Nigel and Rafael,
> > 
> > > As discussed, here are the patches, modified to apply against your
> > > current linux-next tree. A new first patch splits compression
> > > support out into its own file, removing the need to have two
> > > versions of the load_image and save_image routines, minimising the
> > > changes to the remainder of the patches and making things cleaner
> > > than would otherwise be the case.
> > > 
> > > On my laptop, single-threaded compression actually slows writing
> > > down from 175MB/s to around 100-120MB/s (depending on how well the
> > > image compresses). Reading speed improves from 218MB/s to around
> > > 245MB/s. I expect that multithreaded writing would bring the
> > > writing (and reading) speeds back up. It's on my swsusp to do list
> > > :)
> > 
> > Testing this now
> > (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069- dirty).
> 
> Two times I had the rather strange issue that the machine booted
> freshly instead of resuming! First I thought I maybe didn't wait until
> the image was saved, before turning the laptop off. But now it
> happened a second time and also the ThinkPad T42 has a battery in it,
> thus it should always be able to complete writing the image.
> 
> For resuming I found this in the syslog:
> 
> Oct  4 09:19:10 shambhala kernel: end_request: I/O error, dev fd0,
> sector 0
> Oct  4 09:19:10 shambhala kernel: PM: Starting manual resume from disk
> Oct  4 09:19:10 shambhala kernel: PM: Resume from partition 8:2
> Oct  4 09:19:10 shambhala kernel: PM: Checking hibernation image.
> Oct  4 09:19:10 shambhala kernel: PM: Error -22 checking image file
> Oct  4 09:19:10 shambhala kernel: PM: Resume from disk failed.
> Oct  4 09:19:10 shambhala kernel: PM: Marking nosave pages:
> 000000000009f000 - 0000000000100000
> Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps created
> Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps freed
> 
> What does error -22 mean?
> 
> For hibernating:
> 
> Oct  4 00:13:09 shambhala ifplugd(eth0)[15127]: Link beat lost.
> Oct  4 00:13:10 shambhala NetworkManager[2146]: <info> (eth0): carrier
> now OFF (device state 1)
> Oct  4 00:13:12 shambhala ifplugd(eth0)[15127]: Exiting.
> Oct  4 00:13:14 shambhala postfix/master[2589]: reload -- version
> 2.7.1, configuration /etc/postfix
> Oct  4 00:13:14 shambhala dhclient: Internet Systems Consortium DHCP
> Client 4.1.1-P1
> Oct  4 00:13:14 shambhala dhclient: Copyright 2004-2010 Internet
> Systems Consortium.
> Oct  4 00:13:14 shambhala dhclient: All rights reserved.
> Oct  4 00:13:14 shambhala dhclient: For info, please visit
> https://www.isc.org/software/dhcp/
> Oct  4 00:13:14 shambhala dhclient:
> Oct  4 00:13:14 shambhala dhclient: Listening on
> LPF/eth0/00:11:25:46:ec:a5
> Oct  4 00:13:14 shambhala dhclient: Sending on
> LPF/eth0/00:11:25:46:ec:a5
> Oct  4 00:13:14 shambhala dhclient: Sending on   Socket/fallback
> Oct  4 00:13:15 shambhala dhclient: DHCPRELEASE on eth0 to 10.0.0.9
> port 67
> Oct  4 00:13:18 shambhala kernel: PM: Marking nosave pages:
> 000000000009f000 - 0000000000100000
> Oct  4 00:13:18 shambhala kernel: PM: Basic memory bitmaps created
> Oct  4 00:13:18 shambhala kernel: PM: Syncing filesystems ... done.
> Oct  4 09:19:10 shambhala kernel: imklog 4.6.4, log source = /proc/kmsg
> started.
> Oct  4 09:19:10 shambhala rsyslogd: [origin software="rsyslogd"
> swVersion="4.6.4" x-pid="1964" x-info="http://www.rsyslog.com"]
> (re)start Oct  4 09:19:10 shambhala kernel: r hub
> Oct  4 09:19:10 shambhala kernel: usbcore: registered new device driver
> usb
> 
> Which is not complete. It seems the last log messages prior to
> hibernating have not fully been written by rsyslog.
> 
> Whats going on there? I didn't see this with Nigel's patches without
> the readahead patch. But then now I am testing suspend next + his
> patches, which may well contain other patches, as far as I understand.
> 
> Any change to test with some newer state of suspend-next?
> 
> Rafael did you integrate Nigel's patches in your tree?

Hmmm, there might be a similarity  between these:

In both times it happened after I made at least one suspend to ram cycle. 
Yesterday I plugged the laptop to my hi-fi and forget to switch on the 
power extension lead. Thus KDE's Power management suspended to RAM after 
15 minutes of inactivity.

So maybe suspend to RAM interferes somehow.

Additionally I tend to get Radeon DRM KMS graphics corruption with that 
kernel. And even a complete lockup once.

I think I will try 2.6.35-rc5 or whatever is latest with Nigel's patches 
from Nigel's for-rafael branch in order to isolate whether what I see is 
an issue with Nigel's patches or with any of the other stuff in suspend-
next.

Unless to have some newer stuff for me to test with.

-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] Swsusp patches applied to suspend-2.6#linux-next
  2010-10-04  8:31     ` [linux-pm] " Nigel Cunningham
@ 2010-10-04  8:55       ` Martin Steigerwald
  2010-10-04  8:55       ` Martin Steigerwald
  1 sibling, 0 replies; 113+ messages in thread
From: Martin Steigerwald @ 2010-10-04  8:55 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: linux-pm, Nigel Cunningham, LKML, TuxOnIce-devel

Am Montag 04 Oktober 2010 schrieb Nigel Cunningham:
> Hi Martin.

Hi Nigel,

> On 04/10/10 19:00, Martin Steigerwald wrote:
> > Am Samstag 02 Oktober 2010 schrieb Martin Steigerwald:
> >> Am Montag 27 September 2010 schrieb Nigel Cunningham:
> >>> Hi again Rafael.
> >> 
> >> Hi Nigel and Rafael,
> >> 
> >>> As discussed, here are the patches, modified to apply against your
> >>> current linux-next tree. A new first patch splits compression
> >>> support out into its own file, removing the need to have two
> >>> versions of the load_image and save_image routines, minimising the
> >>> changes to the remainder of the patches and making things cleaner
> >>> than would otherwise be the case.
> >>> 
> >>> On my laptop, single-threaded compression actually slows writing
> >>> down from 175MB/s to around 100-120MB/s (depending on how well the
> >>> image compresses). Reading speed improves from 218MB/s to around
> >>> 245MB/s. I expect that multithreaded writing would bring the
> >>> writing (and reading) speeds back up. It's on my swsusp to do list
> >>> :)
> >> 
> >> Testing this now
> >> (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069- dirty).
> > 
> > Two times I had the rather strange issue that the machine booted
> > freshly instead of resuming! First I thought I maybe didn't wait
> > until the image was saved, before turning the laptop off. But now it
> > happened a second time and also the ThinkPad T42 has a battery in
> > it, thus it should always be able to complete writing the image.
> > 
> > For resuming I found this in the syslog:
> > 
> > Oct  4 09:19:10 shambhala kernel: end_request: I/O error, dev fd0,
> > sector 0
> > Oct  4 09:19:10 shambhala kernel: PM: Starting manual resume from
> > disk Oct  4 09:19:10 shambhala kernel: PM: Resume from partition 8:2
> > Oct  4 09:19:10 shambhala kernel: PM: Checking hibernation image.
> > Oct  4 09:19:10 shambhala kernel: PM: Error -22 checking image file
> > Oct  4 09:19:10 shambhala kernel: PM: Resume from disk failed. Oct 
> > 4 09:19:10 shambhala kernel: PM: Marking nosave pages:
> > 000000000009f000 - 0000000000100000
> > Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps created
> > Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps freed
> > 
> > What does error -22 mean?
> 
> -22 is -EINVAL. There are a few reasons that it could occur, but rather
> than chasing our tails, how about if I just tell you that I've been
> working on a new version of the patches that will provide more detailed
> debugging of issues like this (printks that can be enabled/disabled at
> run time) - and hopefully address your issue so it won't happen anyway.

Ok, then I switch back to a stable kernel for the time being.

Please notify me when you have something to test for me.

> > For hibernating:
> > 
> > Oct  4 00:13:09 shambhala ifplugd(eth0)[15127]: Link beat lost.
> > Oct  4 00:13:10 shambhala NetworkManager[2146]:<info>  (eth0):
> > carrier now OFF (device state 1)
[...]
> > Which is not complete. It seems the last log messages prior to
> > hibernating have not fully been written by rsyslog.
> 
> That's not unusual - after we do the atomic copy, nothing gets logged.

I thought so. I think its usually logged after resume?

Thanks,
-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: Swsusp patches applied to suspend-2.6#linux-next
  2010-10-04  8:31     ` [linux-pm] " Nigel Cunningham
  2010-10-04  8:55       ` Martin Steigerwald
@ 2010-10-04  8:55       ` Martin Steigerwald
  1 sibling, 0 replies; 113+ messages in thread
From: Martin Steigerwald @ 2010-10-04  8:55 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: TuxOnIce-devel, linux-pm, Nigel Cunningham, LKML

Am Montag 04 Oktober 2010 schrieb Nigel Cunningham:
> Hi Martin.

Hi Nigel,

> On 04/10/10 19:00, Martin Steigerwald wrote:
> > Am Samstag 02 Oktober 2010 schrieb Martin Steigerwald:
> >> Am Montag 27 September 2010 schrieb Nigel Cunningham:
> >>> Hi again Rafael.
> >> 
> >> Hi Nigel and Rafael,
> >> 
> >>> As discussed, here are the patches, modified to apply against your
> >>> current linux-next tree. A new first patch splits compression
> >>> support out into its own file, removing the need to have two
> >>> versions of the load_image and save_image routines, minimising the
> >>> changes to the remainder of the patches and making things cleaner
> >>> than would otherwise be the case.
> >>> 
> >>> On my laptop, single-threaded compression actually slows writing
> >>> down from 175MB/s to around 100-120MB/s (depending on how well the
> >>> image compresses). Reading speed improves from 218MB/s to around
> >>> 245MB/s. I expect that multithreaded writing would bring the
> >>> writing (and reading) speeds back up. It's on my swsusp to do list
> >>> :)
> >> 
> >> Testing this now
> >> (2.6.36-rc4-tp42-suspend-next-vmembase-0-00253-gab9b069- dirty).
> > 
> > Two times I had the rather strange issue that the machine booted
> > freshly instead of resuming! First I thought I maybe didn't wait
> > until the image was saved, before turning the laptop off. But now it
> > happened a second time and also the ThinkPad T42 has a battery in
> > it, thus it should always be able to complete writing the image.
> > 
> > For resuming I found this in the syslog:
> > 
> > Oct  4 09:19:10 shambhala kernel: end_request: I/O error, dev fd0,
> > sector 0
> > Oct  4 09:19:10 shambhala kernel: PM: Starting manual resume from
> > disk Oct  4 09:19:10 shambhala kernel: PM: Resume from partition 8:2
> > Oct  4 09:19:10 shambhala kernel: PM: Checking hibernation image.
> > Oct  4 09:19:10 shambhala kernel: PM: Error -22 checking image file
> > Oct  4 09:19:10 shambhala kernel: PM: Resume from disk failed. Oct 
> > 4 09:19:10 shambhala kernel: PM: Marking nosave pages:
> > 000000000009f000 - 0000000000100000
> > Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps created
> > Oct  4 09:19:10 shambhala kernel: PM: Basic memory bitmaps freed
> > 
> > What does error -22 mean?
> 
> -22 is -EINVAL. There are a few reasons that it could occur, but rather
> than chasing our tails, how about if I just tell you that I've been
> working on a new version of the patches that will provide more detailed
> debugging of issues like this (printks that can be enabled/disabled at
> run time) - and hopefully address your issue so it won't happen anyway.

Ok, then I switch back to a stable kernel for the time being.

Please notify me when you have something to test for me.

> > For hibernating:
> > 
> > Oct  4 00:13:09 shambhala ifplugd(eth0)[15127]: Link beat lost.
> > Oct  4 00:13:10 shambhala NetworkManager[2146]:<info>  (eth0):
> > carrier now OFF (device state 1)
[...]
> > Which is not complete. It seems the last log messages prior to
> > hibernating have not fully been written by rsyslog.
> 
> That's not unusual - after we do the atomic copy, nothing gets logged.

I thought so. I think its usually logged after resume?

Thanks,
-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] [PATCH 07/23] Hiberation: Fix speed display.
  2010-09-27  5:43 ` [PATCH 07/23] Hiberation: Fix speed display Nigel Cunningham
  2010-10-04 17:51   ` Pavel Machek
@ 2010-10-04 17:51   ` Pavel Machek
  1 sibling, 0 replies; 113+ messages in thread
From: Pavel Machek @ 2010-10-04 17:51 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

On Mon 2010-09-27 15:43:42, Nigel Cunningham wrote:
> Correct the situation where, if an error occurs while writing an image,
> the speed display still uses the number of pages that should have been
> written, rather than the number of pages that were written.
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>

Ack.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 07/23] Hiberation: Fix speed display.
  2010-09-27  5:43 ` [PATCH 07/23] Hiberation: Fix speed display Nigel Cunningham
@ 2010-10-04 17:51   ` Pavel Machek
  2010-10-04 17:51   ` [linux-pm] " Pavel Machek
  1 sibling, 0 replies; 113+ messages in thread
From: Pavel Machek @ 2010-10-04 17:51 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Mon 2010-09-27 15:43:42, Nigel Cunningham wrote:
> Correct the situation where, if an error occurs while writing an image,
> the speed display still uses the number of pages that should have been
> written, rather than the number of pages that were written.
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>

Ack.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] [PATCH 08/23] Hibernation: Generic extents support.
  2010-09-27  5:43 ` Nigel Cunningham
  2010-10-04 17:51   ` Pavel Machek
@ 2010-10-04 17:51   ` Pavel Machek
  2010-10-06  1:21     ` Nigel Cunningham
  2010-10-06  1:21     ` [linux-pm] " Nigel Cunningham
  1 sibling, 2 replies; 113+ messages in thread
From: Pavel Machek @ 2010-10-04 17:51 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi!

> Separate out the extent storage and manipulation into a separate
> file and make them more generic, so we can also use extents for
> recording what sectors are used and (later) support multiple
> storage devices more easily.
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>

> @@ -0,0 +1,125 @@
> +/*
> + * linux/kernel/power/extents.c
> + *
> + * This file provides functions for storing and using a series of
> + * extents.
> + *
> + * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz>

That address is no longer valid :-(. Jiri Kosina should already have
patches to remove it elsewhere in the tree.


> +/**
> + *	free_all_swap_pages - free swap pages allocated for saving image data.
> + *	It also frees the extents used to register which swap entres had been
> + *	allocated.
> + */
> +
> +void hib_extents_clear(struct hib_extent_state *pos)

Comment does not match function.



-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 08/23] Hibernation: Generic extents support.
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-10-04 17:51   ` Pavel Machek
  2010-10-04 17:51   ` [linux-pm] " Pavel Machek
  1 sibling, 0 replies; 113+ messages in thread
From: Pavel Machek @ 2010-10-04 17:51 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi!

> Separate out the extent storage and manipulation into a separate
> file and make them more generic, so we can also use extents for
> recording what sectors are used and (later) support multiple
> storage devices more easily.
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>

> @@ -0,0 +1,125 @@
> +/*
> + * linux/kernel/power/extents.c
> + *
> + * This file provides functions for storing and using a series of
> + * extents.
> + *
> + * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz>

That address is no longer valid :-(. Jiri Kosina should already have
patches to remove it elsewhere in the tree.


> +/**
> + *	free_all_swap_pages - free swap pages allocated for saving image data.
> + *	It also frees the extents used to register which swap entres had been
> + *	allocated.
> + */
> +
> +void hib_extents_clear(struct hib_extent_state *pos)

Comment does not match function.



-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] [PATCH 03/23] Hibernation: Swap iteration functions.
  2010-09-27  5:43 ` Nigel Cunningham
@ 2010-10-04 17:54   ` Pavel Machek
  2010-10-06  1:22     ` Nigel Cunningham
  2010-10-06  1:22     ` Nigel Cunningham
  2010-10-04 17:54   ` Pavel Machek
  1 sibling, 2 replies; 113+ messages in thread
From: Pavel Machek @ 2010-10-04 17:54 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

On Mon 2010-09-27 15:43:38, Nigel Cunningham wrote:
> Add the data structure 'storage_position' and routines that allow
> a caller to iterate over swap in sector order. Note that calling
> reset_storage_pos only resets the position. next_swapdev_block
> must also be called to get the address of the first (and subsequent
> sectors).
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>

Merge this with 8/23? AFAICT, this creates unused functions here only
to move them in later patch.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 03/23] Hibernation: Swap iteration functions.
  2010-09-27  5:43 ` Nigel Cunningham
  2010-10-04 17:54   ` [linux-pm] " Pavel Machek
@ 2010-10-04 17:54   ` Pavel Machek
  1 sibling, 0 replies; 113+ messages in thread
From: Pavel Machek @ 2010-10-04 17:54 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

On Mon 2010-09-27 15:43:38, Nigel Cunningham wrote:
> Add the data structure 'storage_position' and routines that allow
> a caller to iterate over swap in sector order. Note that calling
> reset_storage_pos only resets the position. next_swapdev_block
> must also be called to get the address of the first (and subsequent
> sectors).
> 
> Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>

Merge this with 8/23? AFAICT, this creates unused functions here only
to move them in later patch.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] [PATCH 08/23] Hibernation: Generic extents support.
  2010-10-04 17:51   ` [linux-pm] " Pavel Machek
  2010-10-06  1:21     ` Nigel Cunningham
@ 2010-10-06  1:21     ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-06  1:21 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi.

On 05/10/10 04:51, Pavel Machek wrote:
> Hi!
>
>> Separate out the extent storage and manipulation into a separate
>> file and make them more generic, so we can also use extents for
>> recording what sectors are used and (later) support multiple
>> storage devices more easily.
>>
>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>
>> @@ -0,0 +1,125 @@
>> +/*
>> + * linux/kernel/power/extents.c
>> + *
>> + * This file provides functions for storing and using a series of
>> + * extents.
>> + *
>> + * Copyright (C) 1998,2001-2005 Pavel Machek<pavel@suse.cz>
>
> That address is no longer valid :-(. Jiri Kosina should already have
> patches to remove it elsewhere in the tree.

Okay. You want ucw.cz or something else?

>> +/**
>> + *	free_all_swap_pages - free swap pages allocated for saving image data.
>> + *	It also frees the extents used to register which swap entres had been
>> + *	allocated.
>> + */
>> +
>> +void hib_extents_clear(struct hib_extent_state *pos)
>
> Comment does not match function.

Thanks.

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 08/23] Hibernation: Generic extents support.
  2010-10-04 17:51   ` [linux-pm] " Pavel Machek
@ 2010-10-06  1:21     ` Nigel Cunningham
  2010-10-06  1:21     ` [linux-pm] " Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-06  1:21 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 05/10/10 04:51, Pavel Machek wrote:
> Hi!
>
>> Separate out the extent storage and manipulation into a separate
>> file and make them more generic, so we can also use extents for
>> recording what sectors are used and (later) support multiple
>> storage devices more easily.
>>
>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>
>> @@ -0,0 +1,125 @@
>> +/*
>> + * linux/kernel/power/extents.c
>> + *
>> + * This file provides functions for storing and using a series of
>> + * extents.
>> + *
>> + * Copyright (C) 1998,2001-2005 Pavel Machek<pavel@suse.cz>
>
> That address is no longer valid :-(. Jiri Kosina should already have
> patches to remove it elsewhere in the tree.

Okay. You want ucw.cz or something else?

>> +/**
>> + *	free_all_swap_pages - free swap pages allocated for saving image data.
>> + *	It also frees the extents used to register which swap entres had been
>> + *	allocated.
>> + */
>> +
>> +void hib_extents_clear(struct hib_extent_state *pos)
>
> Comment does not match function.

Thanks.

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [linux-pm] [PATCH 03/23] Hibernation: Swap iteration functions.
  2010-10-04 17:54   ` [linux-pm] " Pavel Machek
@ 2010-10-06  1:22     ` Nigel Cunningham
  2010-10-06  1:22     ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-06  1:22 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi.

On 05/10/10 04:54, Pavel Machek wrote:
> On Mon 2010-09-27 15:43:38, Nigel Cunningham wrote:
>> Add the data structure 'storage_position' and routines that allow
>> a caller to iterate over swap in sector order. Note that calling
>> reset_storage_pos only resets the position. next_swapdev_block
>> must also be called to get the address of the first (and subsequent
>> sectors).
>>
>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>
> Merge this with 8/23? AFAICT, this creates unused functions here only
> to move them in later patch.

Okay. I've merged a couple of the others together too. I hope to send a 
new set in a while.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 03/23] Hibernation: Swap iteration functions.
  2010-10-04 17:54   ` [linux-pm] " Pavel Machek
  2010-10-06  1:22     ` Nigel Cunningham
@ 2010-10-06  1:22     ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-06  1:22 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 05/10/10 04:54, Pavel Machek wrote:
> On Mon 2010-09-27 15:43:38, Nigel Cunningham wrote:
>> Add the data structure 'storage_position' and routines that allow
>> a caller to iterate over swap in sector order. Note that calling
>> reset_storage_pos only resets the position. next_swapdev_block
>> must also be called to get the address of the first (and subsequent
>> sectors).
>>
>> Signed-off-by: Nigel Cunningham<nigel@tuxonice.net>
>
> Merge this with 8/23? AFAICT, this creates unused functions here only
> to move them in later patch.

Okay. I've merged a couple of the others together too. I hope to send a 
new set in a while.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 13/23] Hibernation: Partial page I/O support.
  2010-09-27  5:43 ` [PATCH 13/23] Hibernation: Partial page I/O support Nigel Cunningham
  2010-10-13  7:10   ` Pavel Machek
@ 2010-10-13  7:10   ` Pavel Machek
  2010-10-13 20:28     ` Rafael J. Wysocki
  2010-10-13 20:28     ` Rafael J. Wysocki
  1 sibling, 2 replies; 113+ messages in thread
From: Pavel Machek @ 2010-10-13  7:10 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi!

> Add functions that can be used for coalescing and splitting buffers
> that are smaller than PAGE_SIZE. These functions provide no method
> of determining where the boundaries of the smaller buffers are to
> be found - that is the caller's problem.

I don't get it; why do we need that support?


> +int hib_write_buffer(char *buffer, int buffer_size)
> +{
> +	int bytes_left = buffer_size, result = 0;
> +
> +	while (bytes_left) {
> +		char *from = buffer + buffer_size - bytes_left;
> +		char *to = hib_ppio_buffer + hib_ppio_buffer_posn;
> +		int capacity = PAGE_SIZE - hib_ppio_buffer_posn;
> +
> +		if (bytes_left <= capacity) {
> +			memcpy(to, from, bytes_left);
> +			hib_ppio_buffer_posn += bytes_left;
> +			return 0;
> +		}
> +
> +		/* Complete this page and start a new one */
> +		memcpy(to, from, capacity);
> +		bytes_left -= capacity;

If this copy happens too often, it will slow stuff down...
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 13/23] Hibernation: Partial page I/O support.
  2010-09-27  5:43 ` [PATCH 13/23] Hibernation: Partial page I/O support Nigel Cunningham
@ 2010-10-13  7:10   ` Pavel Machek
  2010-10-13  7:10   ` Pavel Machek
  1 sibling, 0 replies; 113+ messages in thread
From: Pavel Machek @ 2010-10-13  7:10 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi!

> Add functions that can be used for coalescing and splitting buffers
> that are smaller than PAGE_SIZE. These functions provide no method
> of determining where the boundaries of the smaller buffers are to
> be found - that is the caller's problem.

I don't get it; why do we need that support?


> +int hib_write_buffer(char *buffer, int buffer_size)
> +{
> +	int bytes_left = buffer_size, result = 0;
> +
> +	while (bytes_left) {
> +		char *from = buffer + buffer_size - bytes_left;
> +		char *to = hib_ppio_buffer + hib_ppio_buffer_posn;
> +		int capacity = PAGE_SIZE - hib_ppio_buffer_posn;
> +
> +		if (bytes_left <= capacity) {
> +			memcpy(to, from, bytes_left);
> +			hib_ppio_buffer_posn += bytes_left;
> +			return 0;
> +		}
> +
> +		/* Complete this page and start a new one */
> +		memcpy(to, from, capacity);
> +		bytes_left -= capacity;

If this copy happens too often, it will slow stuff down...
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 13/23] Hibernation: Partial page I/O support.
  2010-10-13  7:10   ` Pavel Machek
  2010-10-13 20:28     ` Rafael J. Wysocki
@ 2010-10-13 20:28     ` Rafael J. Wysocki
  2010-10-13 21:17       ` Nigel Cunningham
  2010-10-13 21:17       ` Nigel Cunningham
  1 sibling, 2 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-10-13 20:28 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Nigel Cunningham, Linux PM, LKML, TuxOnIce-devel

On Wednesday, October 13, 2010, Pavel Machek wrote:
> Hi!
> 
> > Add functions that can be used for coalescing and splitting buffers
> > that are smaller than PAGE_SIZE. These functions provide no method
> > of determining where the boundaries of the smaller buffers are to
> > be found - that is the caller's problem.
> 
> I don't get it; why do we need that support?

This is related to compression.  This way we can put data from two or more
compressed pages into one page frame.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 13/23] Hibernation: Partial page I/O support.
  2010-10-13  7:10   ` Pavel Machek
@ 2010-10-13 20:28     ` Rafael J. Wysocki
  2010-10-13 20:28     ` Rafael J. Wysocki
  1 sibling, 0 replies; 113+ messages in thread
From: Rafael J. Wysocki @ 2010-10-13 20:28 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Linux PM, LKML, TuxOnIce-devel

On Wednesday, October 13, 2010, Pavel Machek wrote:
> Hi!
> 
> > Add functions that can be used for coalescing and splitting buffers
> > that are smaller than PAGE_SIZE. These functions provide no method
> > of determining where the boundaries of the smaller buffers are to
> > be found - that is the caller's problem.
> 
> I don't get it; why do we need that support?

This is related to compression.  This way we can put data from two or more
compressed pages into one page frame.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 13/23] Hibernation: Partial page I/O support.
  2010-10-13 20:28     ` Rafael J. Wysocki
  2010-10-13 21:17       ` Nigel Cunningham
@ 2010-10-13 21:17       ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-13 21:17 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Pavel Machek, Linux PM, LKML, TuxOnIce-devel

Hi.

On 14/10/10 07:28, Rafael J. Wysocki wrote:
> On Wednesday, October 13, 2010, Pavel Machek wrote:
>> Hi!
>>
>>> Add functions that can be used for coalescing and splitting buffers
>>> that are smaller than PAGE_SIZE. These functions provide no method
>>> of determining where the boundaries of the smaller buffers are to
>>> be found - that is the caller's problem.
>>
>> I don't get it; why do we need that support?
>
> This is related to compression.  This way we can put data from two or more
> compressed pages into one page frame.

It also provides a simple way of putting information from multiple 
sources into a larger-than-at-the-moment header:

- Which pfns are stored
- What swap extents are used
- What devices are used (dev_t, UUID, last mount time for each)
- Whether compression is enabled and what algo is used (if made 
configurable)

and so on.

I do see the logic to Pavel's question though - the last set of patches 
I sent didn't switch the compression code over to using this support. 
That change would make their usefulness a lot clearer.

Regarding speed, I haven't measured the difference but would expect that 
the cost of combining and splitting pages in this way would be less than 
that of waiting on extra I/O. In addition, if we merge the pages in this 
way, our image size will be much closer to the compression ratio and 
will therefore make it more feasible for us to estimate how much storage 
is needed, taking into account an expected compression ratio (which is 
what TuxOnIce currently does).

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [PATCH 13/23] Hibernation: Partial page I/O support.
  2010-10-13 20:28     ` Rafael J. Wysocki
@ 2010-10-13 21:17       ` Nigel Cunningham
  2010-10-13 21:17       ` Nigel Cunningham
  1 sibling, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-10-13 21:17 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linux PM, LKML, TuxOnIce-devel

Hi.

On 14/10/10 07:28, Rafael J. Wysocki wrote:
> On Wednesday, October 13, 2010, Pavel Machek wrote:
>> Hi!
>>
>>> Add functions that can be used for coalescing and splitting buffers
>>> that are smaller than PAGE_SIZE. These functions provide no method
>>> of determining where the boundaries of the smaller buffers are to
>>> be found - that is the caller's problem.
>>
>> I don't get it; why do we need that support?
>
> This is related to compression.  This way we can put data from two or more
> compressed pages into one page frame.

It also provides a simple way of putting information from multiple 
sources into a larger-than-at-the-moment header:

- Which pfns are stored
- What swap extents are used
- What devices are used (dev_t, UUID, last mount time for each)
- Whether compression is enabled and what algo is used (if made 
configurable)

and so on.

I do see the logic to Pavel's question though - the last set of patches 
I sent didn't switch the compression code over to using this support. 
That change would make their usefulness a lot clearer.

Regarding speed, I haven't measured the difference but would expect that 
the cost of combining and splitting pages in this way would be less than 
that of waiting on extra I/O. In addition, if we merge the pages in this 
way, our image size will be much closer to the compression ratio and 
will therefore make it more feasible for us to estimate how much storage 
is needed, taking into account an expected compression ratio (which is 
what TuxOnIce currently does).

Regards,

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Swsusp patches applied to suspend-2.6#linux-next
@ 2010-09-27  5:43 Nigel Cunningham
  0 siblings, 0 replies; 113+ messages in thread
From: Nigel Cunningham @ 2010-09-27  5:43 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux PM, LKML, TuxOnIce-devel

Hi again Rafael.

As discussed, here are the patches, modified to apply against your current
linux-next tree. A new first patch splits compression support out into its
own file, removing the need to have two versions of the load_image and
save_image routines, minimising the changes to the remainder of the
patches and making things cleaner than would otherwise be the case.

On my laptop, single-threaded compression actually slows writing down from
175MB/s to around 100-120MB/s (depending on how well the image compresses).
Reading speed improves from 218MB/s to around 245MB/s. I expect that
multithreaded writing would bring the writing (and reading) speeds back
up. It's on my swsusp to do list :)

Nigel

^ permalink raw reply	[flat|nested] 113+ messages in thread

end of thread, other threads:[~2010-10-13 21:17 UTC | newest]

Thread overview: 113+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-27  5:43 Swsusp patches applied to suspend-2.6#linux-next Nigel Cunningham
2010-09-27  5:43 ` [PATCH 01/23] Hibernation: Split compression support out Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27 20:27   ` Rafael J. Wysocki
2010-09-27 20:32     ` Nigel Cunningham
2010-09-27 20:32     ` Nigel Cunningham
2010-10-01 21:28       ` Rafael J. Wysocki
2010-10-01 21:28       ` Rafael J. Wysocki
2010-10-01 21:45         ` Nigel Cunningham
2010-10-01 21:45         ` Nigel Cunningham
2010-10-01 22:15           ` Rafael J. Wysocki
2010-10-01 22:15           ` Rafael J. Wysocki
2010-09-27 20:27   ` Rafael J. Wysocki
2010-09-27  5:43 ` [PATCH 02/23] Record & display i/o speed post resume Nigel Cunningham
2010-09-27 20:06   ` Rafael J. Wysocki
2010-09-27 20:06   ` Rafael J. Wysocki
2010-09-27 20:26     ` Nigel Cunningham
2010-09-27 20:49       ` Rafael J. Wysocki
2010-09-27 21:05         ` Nigel Cunningham
2010-09-27 21:16           ` Rafael J. Wysocki
2010-09-27 21:16           ` Rafael J. Wysocki
2010-09-27 21:05         ` Nigel Cunningham
2010-09-27 20:49       ` Rafael J. Wysocki
2010-09-27 20:26     ` Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 03/23] Hibernation: Swap iteration functions Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-10-04 17:54   ` [linux-pm] " Pavel Machek
2010-10-06  1:22     ` Nigel Cunningham
2010-10-06  1:22     ` Nigel Cunningham
2010-10-04 17:54   ` Pavel Machek
2010-09-27  5:43 ` [PATCH 04/23] Hibernation: Move root_swap declaration Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 05/23] Hibernation: Add mass swap allocation routine Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 06/23] Hibernation: Switch to preallocating swap Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 07/23] Hiberation: Fix speed display Nigel Cunningham
2010-10-04 17:51   ` Pavel Machek
2010-10-04 17:51   ` [linux-pm] " Pavel Machek
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 08/23] Hibernation: Generic extents support Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-10-04 17:51   ` Pavel Machek
2010-10-04 17:51   ` [linux-pm] " Pavel Machek
2010-10-06  1:21     ` Nigel Cunningham
2010-10-06  1:21     ` [linux-pm] " Nigel Cunningham
2010-09-27  5:43 ` [PATCH 09/23] Hibernation: Iterate over sectors not swap entries Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 10/23] Hibernation: Stop passing swap_map_handle struct Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 11/23] Hibernation: Stop passing bio_chain around Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 12/23] Hibernation: Move block i/o fns to block_io.c Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 13/23] Hibernation: Partial page I/O support Nigel Cunningham
2010-10-13  7:10   ` Pavel Machek
2010-10-13  7:10   ` Pavel Machek
2010-10-13 20:28     ` Rafael J. Wysocki
2010-10-13 20:28     ` Rafael J. Wysocki
2010-10-13 21:17       ` Nigel Cunningham
2010-10-13 21:17       ` Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 14/23] Hibernation: Store block extents at start of image Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 15/23] Hibernation: Use block extents for reading image Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 16/23] Remove first_sector from swap_map_handle Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 17/23] Hibernation: Replace bio chain Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 18/23] Hibernation: Remove swap_map_pages Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 19/23] Hibernation: Remove wait_on_bio_chain result Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 20/23] Hibernation: Prepare for handle.cur removal Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 21/23] Hibernation: Remove swap_map structure Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 22/23] Hibernation: Remove now-empty routines Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  5:43 ` [PATCH 23/23] Hibernate: Implement readahead when resuming Nigel Cunningham
2010-09-27  5:43 ` Nigel Cunningham
2010-09-27  6:59 ` [TuxOnIce-devel] Swsusp patches applied to suspend-2.6#linux-next Andrey Rahmatullin
2010-09-27  6:59   ` Andrey Rahmatullin
2010-09-27  8:28   ` Nigel Cunningham
2010-09-27  8:28   ` Nigel Cunningham
2010-09-27  8:00 ` Andrey Rahmatullin
2010-09-27  8:00 ` Andrey Rahmatullin
2010-09-27  8:29   ` Nigel Cunningham
2010-09-27  8:29   ` Nigel Cunningham
2010-09-27  9:38     ` Andrey Rahmatullin
2010-09-27  9:57       ` Nigel Cunningham
2010-09-27  9:57       ` Nigel Cunningham
2010-09-27  9:38     ` Andrey Rahmatullin
2010-09-27 11:16     ` Andrey Rahmatullin
2010-09-27 11:16     ` Andrey Rahmatullin
2010-09-27 11:39       ` Nigel Cunningham
2010-09-27 11:39       ` Nigel Cunningham
2010-10-02 16:49 ` Martin Steigerwald
2010-10-02 16:49 ` [linux-pm] " Martin Steigerwald
2010-10-04  8:00   ` Martin Steigerwald
2010-10-04  8:00   ` [linux-pm] " Martin Steigerwald
2010-10-04  8:31     ` Nigel Cunningham
2010-10-04  8:31     ` [linux-pm] " Nigel Cunningham
2010-10-04  8:55       ` Martin Steigerwald
2010-10-04  8:55       ` Martin Steigerwald
2010-10-04  8:47     ` Martin Steigerwald
2010-10-04  8:47     ` [linux-pm] " Martin Steigerwald
  -- strict thread matches above, loose matches on Subject: below --
2010-09-27  5:43 Nigel Cunningham

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.