lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 27 Sep 2010 15:43:36 +1000
From:	Nigel Cunningham <nigel@...onice.net>
To:	"Rafael J. Wysocki" <rjw@...k.pl>,
	Linux PM <linux-pm@...ts.linux-foundation.org>,
	LKML <linux-kernel@...r.kernel.org>,
	TuxOnIce-devel <tuxonice-devel@...onice.net>
Subject: [PATCH 01/23] Hibernation: Split compression support out.

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@...onice.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@...onice.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@...onice.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@...onice.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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ