From: Bojan Smojver <bojan@rexursive.com>
To: linux-kernel@vger.kernel.org
Subject: Re: [PATCH]: Compress hibernation image with LZO (in-kernel)
Date: Fri, 30 Jul 2010 20:44:27 +1000 [thread overview]
Message-ID: <1280486667.2608.1.camel@shrek.rexursive.com> (raw)
In-Reply-To: <1280465201.2600.10.camel@shrek.rexursive.com>
[-- Attachment #1: Type: text/plain, Size: 149 bytes --]
On Fri, 2010-07-30 at 14:46 +1000, Bojan Smojver wrote:
> This patch speeds up hibernate/thaw operations
This is probably a bit simpler.
--
Bojan
[-- Attachment #2: hibernate-lzo.patch --]
[-- Type: text/x-patch, Size: 6611 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..80aa5a0 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,17 @@ static int swap_writer_finish(struct swap_map_handle *handle,
return error;
}
+#define LZO_HEADER sizeof(size_t)
+#define LZO_ORDER 6
+#define LZO_PAGES (1 << LZO_ORDER)
+#define LZO_SIZE (LZO_PAGES * PAGE_SIZE)
+#define LZO_ADD_PAGES (DIV_ROUND_UP(lzo1x_worst_compress(LZO_SIZE) + \
+ LZO_HEADER, PAGE_SIZE) - LZO_PAGES)
+#define LZO_CMP_PAGES LZO_PAGES
+#define LZO_CMP_SIZE (LZO_CMP_PAGES * PAGE_SIZE)
+#define LZO_UNC_PAGES (LZO_PAGES - LZO_ADD_PAGES)
+#define LZO_UNC_SIZE (LZO_UNC_PAGES * PAGE_SIZE)
+
/**
* save_image - save the suspend image data
*/
@@ -372,6 +384,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_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 +418,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 +467,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_ORDER);
+ vfree(unc);
+ vfree(wrk);
+
return ret;
}
@@ -416,7 +487,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 +619,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_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 +642,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 +702,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_ORDER);
+ vfree(unc);
+
return error;
}
next prev parent reply other threads:[~2010-07-30 10:44 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 [this message]
2010-07-30 22:05 ` Nigel Cunningham
2010-07-30 22:19 ` Bojan Smojver
2010-07-30 23:22 ` Bojan Smojver
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=1280486667.2608.1.camel@shrek.rexursive.com \
--to=bojan@rexursive.com \
--cc=linux-kernel@vger.kernel.org \
/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.