All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bojan Smojver <bojan@rexursive.com>
To: Nigel Cunningham <nigel@tuxonice.net>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH]: Compress hibernation image with LZO (in-kernel)
Date: Sat, 31 Jul 2010 09:22:54 +1000	[thread overview]
Message-ID: <1280532174.2583.1.camel@shrek.rexursive.com> (raw)
In-Reply-To: <4C534C9D.8000600@tuxonice.net>

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

On Sat, 2010-07-31 at 08:05 +1000, Nigel Cunningham wrote:
> Is an order 6 allocation really necessary, 
> though? 

I tried with 5 and 4 and got slightly lower throughput numbers. With 6,
I was getting 145 to 150 MB/s, with 4 I'm getting around 130 MB/s (this
is all on hibernate).

So, here is one with 4.

PS. I guess with this, read_sync can simply disappear as well.

-- 
Bojan

[-- Attachment #2: hibernate-lzo.patch --]
[-- Type: text/x-patch, Size: 6532 bytes --]

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index ca6066a..cb57eb9 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -137,6 +137,8 @@ config SUSPEND_FREEZER
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
+	select LZO_COMPRESS
+	select LZO_DECOMPRESS
 	select SUSPEND_NVS if HAS_IOMEM
 	---help---
 	  Enable the suspend to disk (STD) functionality, which is usually
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index b0bb217..ac33603 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -24,6 +24,7 @@
 #include <linux/swapops.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
+#include <linux/lzo.h>
 
 #include "power.h"
 
@@ -357,6 +358,15 @@ static int swap_writer_finish(struct swap_map_handle *handle,
 	return error;
 }
 
+#define LZO_HEADER	sizeof(size_t)
+#define LZO_CMP_ORDER	4
+#define LZO_CMP_PAGES	(1 << LZO_CMP_ORDER)
+#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
+#define LZO_UNC_PAGES	(2 * LZO_CMP_PAGES - \
+			 DIV_ROUND_UP(lzo1x_worst_compress(LZO_CMP_SIZE) + \
+			              LZO_HEADER, PAGE_SIZE))
+#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
+
 /**
  *	save_image - save the suspend image data
  */
@@ -372,6 +382,30 @@ static int save_image(struct swap_map_handle *handle,
 	struct bio *bio;
 	struct timeval start;
 	struct timeval stop;
+	size_t ul, cl;
+	unsigned char *unc, *cmp;
+	void *wrk;
+
+	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
+	if (!wrk) {
+		printk(KERN_ERR "PM: Failed to allocate LZO workspace\n");
+		return -ENOMEM;
+	}
+
+	unc = vmalloc(LZO_UNC_SIZE);
+	if (!unc) {
+		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
+		vfree(wrk);
+		return -ENOMEM;
+	}
+
+	cmp = (void *)__get_free_pages(__GFP_WAIT | __GFP_HIGH, LZO_CMP_ORDER);
+	if (!cmp) {
+		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
+		vfree(unc);
+		vfree(wrk);
+		return -ENOMEM;
+	}
 
 	printk(KERN_INFO "PM: Saving image data pages (%u pages) ...     ",
 		nr_to_write);
@@ -382,16 +416,46 @@ static int save_image(struct swap_map_handle *handle,
 	bio = NULL;
 	do_gettimeofday(&start);
 	while (1) {
-		ret = snapshot_read_next(snapshot);
-		if (ret <= 0)
+		for (ul = 0; ul < LZO_UNC_SIZE; ul += PAGE_SIZE) {
+			ret = snapshot_read_next(snapshot);
+			if (ret < 0)
+				goto out_finish;
+
+			if (ret == 0)
+				break;
+
+			memcpy(unc + ul, data_of(*snapshot), PAGE_SIZE);
+
+			if (!(nr_pages % m))
+				printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
+			nr_pages++;
+		}
+
+		if (ul == 0)
 			break;
-		ret = swap_write_page(handle, data_of(*snapshot), &bio);
-		if (ret)
+
+		ret = lzo1x_1_compress(unc, ul, cmp + LZO_HEADER, &cl, wrk);
+		if (ret < 0) {
+			printk(KERN_ERR "PM: LZO compression failed\n");
 			break;
-		if (!(nr_pages % m))
-			printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
-		nr_pages++;
+		}
+
+		if (unlikely(cl == 0 || LZO_HEADER + cl > LZO_CMP_SIZE)) {
+			printk(KERN_ERR "PM: Invalid LZO length\n");
+			ret = -1;
+			break;
+		}
+
+		*(size_t *)cmp = cl;
+
+		for (ul = 0; ul < LZO_HEADER + cl; ul += PAGE_SIZE) {
+			ret = swap_write_page(handle, cmp + ul, &bio);
+			if (ret)
+				goto out_finish;
+		}
 	}
+
+out_finish:
 	err2 = hib_wait_on_bio_chain(&bio);
 	do_gettimeofday(&stop);
 	if (!ret)
@@ -401,6 +465,11 @@ static int save_image(struct swap_map_handle *handle,
 	else
 		printk(KERN_CONT "\n");
 	swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+
+	free_pages((unsigned long)cmp, LZO_CMP_ORDER);
+	vfree(unc);
+	vfree(wrk);
+
 	return ret;
 }
 
@@ -416,7 +485,8 @@ static int enough_swap(unsigned int nr_pages)
 	unsigned int free_swap = count_swap_pages(root_swap, 1);
 
 	pr_debug("PM: Free swap pages: %u\n", free_swap);
-	return free_swap > nr_pages + PAGES_FOR_IO;
+	return free_swap >
+	       (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + PAGES_FOR_IO;
 }
 
 /**
@@ -547,9 +617,22 @@ static int load_image(struct swap_map_handle *handle,
 	int error = 0;
 	struct timeval start;
 	struct timeval stop;
-	struct bio *bio;
-	int err2;
 	unsigned nr_pages;
+	size_t ul, cl;
+	unsigned char *unc, *cmp;
+
+	unc = vmalloc(LZO_UNC_SIZE);
+	if (!unc) {
+		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
+		return -ENOMEM;
+	}
+
+	cmp = (void *)__get_free_pages(__GFP_WAIT | __GFP_HIGH, LZO_CMP_ORDER);
+	if (!cmp) {
+		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
+		vfree(unc);
+		return -ENOMEM;
+	}
 
 	printk(KERN_INFO "PM: Loading image data pages (%u pages) ...     ",
 		nr_to_read);
@@ -557,27 +640,58 @@ static int load_image(struct swap_map_handle *handle,
 	if (!m)
 		m = 1;
 	nr_pages = 0;
-	bio = NULL;
 	do_gettimeofday(&start);
+
+	error = snapshot_write_next(snapshot);
+	if (error <= 0)
+		goto out_finish;
+
 	for ( ; ; ) {
-		error = snapshot_write_next(snapshot);
-		if (error <= 0)
-			break;
-		error = swap_read_page(handle, data_of(*snapshot), &bio);
+		error = swap_read_page(handle, cmp, NULL);
 		if (error)
 			break;
-		if (snapshot->sync_read)
-			error = hib_wait_on_bio_chain(&bio);
-		if (error)
+
+		cl = *(size_t *)cmp;
+		if (unlikely(cl == 0 || LZO_HEADER + cl > LZO_CMP_SIZE)) {
+			printk(KERN_ERR "PM: Invalid LZO length\n");
+			error = -1;
+			break;
+		}
+
+		for (ul = PAGE_SIZE; ul < LZO_HEADER + cl; ul += PAGE_SIZE) {
+			error = swap_read_page(handle, cmp + ul, NULL);
+			if (error)
+				goto out_finish;
+		}
+
+		ul = LZO_UNC_SIZE;
+		error = lzo1x_decompress_safe(cmp + LZO_HEADER, cl, unc, &ul);
+		if (error < 0) {
+			printk(KERN_ERR "PM: LZO decompression failed\n");
+			break;
+		}
+
+		if (unlikely(ul == 0 || ul > LZO_UNC_SIZE)) {
+			printk(KERN_ERR "PM: Invalid LZO length\n");
+			error = -1;
 			break;
-		if (!(nr_pages % m))
-			printk("\b\b\b\b%3d%%", nr_pages / m);
-		nr_pages++;
+		}
+
+		for (cl = 0; cl < ul; cl += PAGE_SIZE) {
+			memcpy(data_of(*snapshot), unc + cl, 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;
+		}
 	}
-	err2 = hib_wait_on_bio_chain(&bio);
+
+out_finish:
 	do_gettimeofday(&stop);
-	if (!error)
-		error = err2;
 	if (!error) {
 		printk("\b\b\b\bdone\n");
 		snapshot_write_finalize(snapshot);
@@ -586,6 +700,10 @@ static int load_image(struct swap_map_handle *handle,
 	} else
 		printk("\n");
 	swsusp_show_speed(&start, &stop, nr_to_read, "Read");
+
+	free_pages((unsigned long)cmp, LZO_CMP_ORDER);
+	vfree(unc);
+
 	return error;
 }
 

  parent reply	other threads:[~2010-07-30 23:22 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-30  4:46 [PATCH]: Compress hibernation image with LZO (in-kernel) Bojan Smojver
2010-07-30 10:44 ` Bojan Smojver
2010-07-30 22:05   ` Nigel Cunningham
2010-07-30 22:19     ` Bojan Smojver
2010-07-30 23:22     ` Bojan Smojver [this message]
2010-07-30 23:40       ` Nigel Cunningham
2010-07-31  1:03         ` Bojan Smojver
2010-07-31  1:18           ` Nigel Cunningham
2010-07-31  1:33             ` Bojan Smojver
2010-07-31  4:41               ` Bojan Smojver
2010-07-31  5:03                 ` Bojan Smojver
2010-08-02  0:17                 ` KAMEZAWA Hiroyuki
2010-08-02  0:54                   ` Bojan Smojver
2010-08-02  1:10                     ` KAMEZAWA Hiroyuki
2010-08-02  1:21                       ` Bojan Smojver
2010-08-02  1:27                         ` KAMEZAWA Hiroyuki
2010-08-02  1:43                           ` Bojan Smojver
2010-08-03  1:59                             ` Bojan Smojver
2010-08-03  2:30                               ` Bojan Smojver
2010-08-04  2:42                                 ` Nigel Cunningham
2010-08-04  2:47                                   ` Bojan Smojver
2010-08-04  4:04                                     ` Bojan Smojver
2010-08-04  4:23                                       ` Nigel Cunningham
2010-08-04  5:12                                         ` Bojan Smojver
2010-08-04  5:58                                           ` Bojan Smojver
2010-08-05  1:26                                     ` Bojan Smojver
2010-08-03  6:34                               ` Bojan Smojver
2010-08-04  1:50                               ` Nigel Cunningham
2010-08-04  1:58                                 ` Bojan Smojver
2010-08-04  2:02                                 ` KAMEZAWA Hiroyuki
2010-08-04  2:14                                   ` Bojan Smojver
2010-08-04  2:18                                     ` KAMEZAWA Hiroyuki
2010-08-04  2:37                                       ` Nigel Cunningham
2010-08-04  2:24                                   ` Nigel Cunningham
2010-08-04  2:24                                     ` KAMEZAWA Hiroyuki
2010-08-04  2:38                                       ` Nigel Cunningham
2010-08-05  6:26 ` Pavel Machek
2010-08-05  6:55   ` Bojan Smojver

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1280532174.2583.1.camel@shrek.rexursive.com \
    --to=bojan@rexursive.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nigel@tuxonice.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.