2023-11-15 12:23:26

by Nikhil V

[permalink] [raw]
Subject: [PATCH RESEND v2 0/4] PM: hibernate: LZ4 compression support

This patch series covers the following:
1. Renaming lzo* to generic names, except for lzo_xxx() APIs. This is
used in the next patch where we move to crypto based APIs for
compression. There are no functional changes introduced by this
approach.


2. Replace LZO library calls with crypto generic APIs

Currently for hibernation, LZO is the only compression algorithm
available and uses the existing LZO library calls. However, there
is no flexibility to switch to other algorithms which provides better
results. The main idea is that different compression algorithms have
different characteristics and hibernation may benefit when it uses
alternate algorithms.

By moving to crypto based APIs, it lays a foundation to use other
compression algorithms for hibernation.


3. LZ4 compression

Extend the support for LZ4 compression to be used with hibernation.
The main idea is that different compression algorithms have different
characteristics and hibernation may benefit when it uses any of these
algorithms: a default algorithm, having higher compression rate but is
slower(compression/decompression) and a secondary algorithm, that is
faster(compression/decompression) but has lower compression rate.

LZ4 algorithm has better decompression speeds over LZO. This reduces
the hibernation image restore time.
As per test results:
LZO LZ4
Size before Compression(bytes) 682696704 682393600
Size after Compression(bytes) 146502402 155993547
Decompression Rate 335.02 MB/s 501.05 MB/s
Restore time 4.4s 3.8s

LZO is the default compression algorithm used for hibernation. Enable
CONFIG_HIBERNATION_DEF_COMP_LZ4 to set the default compressor as LZ4.

Compression Benchmarks: https://github.com/lz4/lz4


4. Support to select compression algorithm

Currently the default compression algorithm is selected based on
Kconfig. Introduce a kernel command line parameter "hib_compression" to
override this behaviour.

Users can set "hib_compression" command line parameter to specify
the algorithm.
Usage:
LZO: hib_compression=lzo
LZ4: hib_compression=lz4
LZO is the default compression algorithm used with hibernation.


Changes in v2:
- Fixed build issues reported by kernel test robot for ARCH=sh, [1].
[1] https://lore.kernel.org/oe-kbuild-all/[email protected]/

Nikhil V (4):
PM: hibernate: Rename lzo* to make it generic
PM: hibernate: Move to crypto APIs for LZO compression
PM: hibernate: Add support for LZ4 compression for hibernation
PM: hibernate: Support to select compression algorithm

.../admin-guide/kernel-parameters.txt | 6 +
kernel/power/Kconfig | 26 ++-
kernel/power/hibernate.c | 85 +++++++-
kernel/power/power.h | 19 ++
kernel/power/swap.c | 189 +++++++++++-------
5 files changed, 251 insertions(+), 74 deletions(-)


base-commit: b85ea95d086471afb4ad062012a4d73cd328fa86
--
2.17.1


2023-11-15 12:23:30

by Nikhil V

[permalink] [raw]
Subject: [PATCH RESEND v2 1/4] PM: hibernate: Rename lzo* to make it generic

Renaming lzo* to generic names, except for lzo_xxx() APIs. This is
used in the next patch where we move to crypto based APIs for
compression. There are no functional changes introduced by this
approach.

Signed-off-by: Nikhil V <[email protected]>
---
kernel/power/swap.c | 122 ++++++++++++++++++++++----------------------
1 file changed, 61 insertions(+), 61 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index a2cb0babb5ec..765700f52978 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -515,23 +515,23 @@ static int swap_writer_finish(struct swap_map_handle *handle,
}

/* We need to remember how much compressed data we need to read. */
-#define LZO_HEADER sizeof(size_t)
+#define CMP_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)
+#define UNC_PAGES 32
+#define UNC_SIZE (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)
+/* Number of pages we need for compressed data (worst case). */
+#define CMP_PAGES DIV_ROUND_UP(lzo1x_worst_compress(UNC_SIZE) + \
+ CMP_HEADER, PAGE_SIZE)
+#define CMP_SIZE (CMP_PAGES * PAGE_SIZE)

/* Maximum number of threads for compression/decompression. */
-#define LZO_THREADS 3
+#define CMP_THREADS 3

/* Minimum/maximum number of pages for read buffering. */
-#define LZO_MIN_RD_PAGES 1024
-#define LZO_MAX_RD_PAGES 8192
+#define CMP_MIN_RD_PAGES 1024
+#define CMP_MAX_RD_PAGES 8192


/**
@@ -593,8 +593,8 @@ struct crc_data {
wait_queue_head_t go; /* start crc update */
wait_queue_head_t done; /* crc update done */
u32 *crc32; /* points to handle's crc32 */
- size_t *unc_len[LZO_THREADS]; /* uncompressed lengths */
- unsigned char *unc[LZO_THREADS]; /* uncompressed data */
+ size_t *unc_len[CMP_THREADS]; /* uncompressed lengths */
+ unsigned char *unc[CMP_THREADS]; /* uncompressed data */
};

/*
@@ -625,7 +625,7 @@ static int crc32_threadfn(void *data)
return 0;
}
/*
- * Structure used for LZO data compression.
+ * Structure used for data compression.
*/
struct cmp_data {
struct task_struct *thr; /* thread */
@@ -636,15 +636,15 @@ struct cmp_data {
wait_queue_head_t done; /* compression done */
size_t unc_len; /* uncompressed length */
size_t cmp_len; /* compressed length */
- unsigned char unc[LZO_UNC_SIZE]; /* uncompressed buffer */
- unsigned char cmp[LZO_CMP_SIZE]; /* compressed buffer */
+ unsigned char unc[UNC_SIZE]; /* uncompressed buffer */
+ unsigned char cmp[CMP_SIZE]; /* compressed buffer */
unsigned char wrk[LZO1X_1_MEM_COMPRESS]; /* compression workspace */
};

/*
* Compression function that runs in its own thread.
*/
-static int lzo_compress_threadfn(void *data)
+static int compress_threadfn(void *data)
{
struct cmp_data *d = data;

@@ -661,8 +661,8 @@ static int lzo_compress_threadfn(void *data)
atomic_set(&d->ready, 0);

d->ret = lzo1x_1_compress(d->unc, d->unc_len,
- d->cmp + LZO_HEADER, &d->cmp_len,
- d->wrk);
+ d->cmp + CMP_HEADER, &d->cmp_len,
+ d->wrk);
atomic_set(&d->stop, 1);
wake_up(&d->done);
}
@@ -670,14 +670,14 @@ static int lzo_compress_threadfn(void *data)
}

/**
- * save_image_lzo - Save the suspend image data compressed with LZO.
+ * save_compressed_image - Save the suspend image data after compression.
* @handle: Swap map 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)
+static int save_compressed_image(struct swap_map_handle *handle,
+ struct snapshot_handle *snapshot,
+ unsigned int nr_to_write)
{
unsigned int m;
int ret = 0;
@@ -699,18 +699,18 @@ static int save_image_lzo(struct swap_map_handle *handle,
* footprint.
*/
nr_threads = num_online_cpus() - 1;
- nr_threads = clamp_val(nr_threads, 1, LZO_THREADS);
+ nr_threads = clamp_val(nr_threads, 1, CMP_THREADS);

page = (void *)__get_free_page(GFP_NOIO | __GFP_HIGH);
if (!page) {
- pr_err("Failed to allocate LZO page\n");
+ pr_err("Failed to allocate compression page\n");
ret = -ENOMEM;
goto out_clean;
}

data = vzalloc(array_size(nr_threads, sizeof(*data)));
if (!data) {
- pr_err("Failed to allocate LZO data\n");
+ pr_err("Failed to allocate compression data\n");
ret = -ENOMEM;
goto out_clean;
}
@@ -729,7 +729,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
init_waitqueue_head(&data[thr].go);
init_waitqueue_head(&data[thr].done);

- data[thr].thr = kthread_run(lzo_compress_threadfn,
+ data[thr].thr = kthread_run(compress_threadfn,
&data[thr],
"image_compress/%u", thr);
if (IS_ERR(data[thr].thr)) {
@@ -777,7 +777,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
start = ktime_get();
for (;;) {
for (thr = 0; thr < nr_threads; thr++) {
- for (off = 0; off < LZO_UNC_SIZE; off += PAGE_SIZE) {
+ for (off = 0; off < UNC_SIZE; off += PAGE_SIZE) {
ret = snapshot_read_next(snapshot);
if (ret < 0)
goto out_finish;
@@ -817,14 +817,14 @@ static int save_image_lzo(struct swap_map_handle *handle,
ret = data[thr].ret;

if (ret < 0) {
- pr_err("LZO compression failed\n");
+ pr_err("compression failed\n");
goto out_finish;
}

if (unlikely(!data[thr].cmp_len ||
data[thr].cmp_len >
lzo1x_worst_compress(data[thr].unc_len))) {
- pr_err("Invalid LZO compressed length\n");
+ pr_err("Invalid compressed length\n");
ret = -1;
goto out_finish;
}
@@ -840,7 +840,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
* read it.
*/
for (off = 0;
- off < LZO_HEADER + data[thr].cmp_len;
+ off < CMP_HEADER + data[thr].cmp_len;
off += PAGE_SIZE) {
memcpy(page, data[thr].cmp + off, PAGE_SIZE);

@@ -942,7 +942,7 @@ int swsusp_write(unsigned int flags)
if (!error) {
error = (flags & SF_NOCOMPRESS_MODE) ?
save_image(&handle, &snapshot, pages - 1) :
- save_image_lzo(&handle, &snapshot, pages - 1);
+ save_compressed_image(&handle, &snapshot, pages - 1);
}
out_finish:
error = swap_writer_finish(&handle, flags, error);
@@ -1109,7 +1109,7 @@ static int load_image(struct swap_map_handle *handle,
}

/*
- * Structure used for LZO data decompression.
+ * Structure used for data decompression.
*/
struct dec_data {
struct task_struct *thr; /* thread */
@@ -1120,14 +1120,14 @@ struct dec_data {
wait_queue_head_t done; /* decompression done */
size_t unc_len; /* uncompressed length */
size_t cmp_len; /* compressed length */
- unsigned char unc[LZO_UNC_SIZE]; /* uncompressed buffer */
- unsigned char cmp[LZO_CMP_SIZE]; /* compressed buffer */
+ unsigned char unc[UNC_SIZE]; /* uncompressed buffer */
+ unsigned char cmp[CMP_SIZE]; /* compressed buffer */
};

/*
* Decompression function that runs in its own thread.
*/
-static int lzo_decompress_threadfn(void *data)
+static int decompress_threadfn(void *data)
{
struct dec_data *d = data;

@@ -1143,9 +1143,9 @@ static int lzo_decompress_threadfn(void *data)
}
atomic_set(&d->ready, 0);

- d->unc_len = LZO_UNC_SIZE;
- d->ret = lzo1x_decompress_safe(d->cmp + LZO_HEADER, d->cmp_len,
- d->unc, &d->unc_len);
+ d->unc_len = UNC_SIZE;
+ d->ret = lzo1x_decompress_safe(d->cmp + CMP_HEADER, d->cmp_len,
+ d->unc, &d->unc_len);
if (clean_pages_on_decompress)
flush_icache_range((unsigned long)d->unc,
(unsigned long)d->unc + d->unc_len);
@@ -1157,14 +1157,14 @@ static int lzo_decompress_threadfn(void *data)
}

/**
- * load_image_lzo - Load compressed image data and decompress them with LZO.
+ * load_compressed_image - Load compressed image data and decompress it.
* @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)
+static int load_compressed_image(struct swap_map_handle *handle,
+ struct snapshot_handle *snapshot,
+ unsigned int nr_to_read)
{
unsigned int m;
int ret = 0;
@@ -1189,18 +1189,18 @@ static int load_image_lzo(struct swap_map_handle *handle,
* footprint.
*/
nr_threads = num_online_cpus() - 1;
- nr_threads = clamp_val(nr_threads, 1, LZO_THREADS);
+ nr_threads = clamp_val(nr_threads, 1, CMP_THREADS);

- page = vmalloc(array_size(LZO_MAX_RD_PAGES, sizeof(*page)));
+ page = vmalloc(array_size(CMP_MAX_RD_PAGES, sizeof(*page)));
if (!page) {
- pr_err("Failed to allocate LZO page\n");
+ pr_err("Failed to allocate compression page\n");
ret = -ENOMEM;
goto out_clean;
}

data = vzalloc(array_size(nr_threads, sizeof(*data)));
if (!data) {
- pr_err("Failed to allocate LZO data\n");
+ pr_err("Failed to allocate compression data\n");
ret = -ENOMEM;
goto out_clean;
}
@@ -1221,7 +1221,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
init_waitqueue_head(&data[thr].go);
init_waitqueue_head(&data[thr].done);

- data[thr].thr = kthread_run(lzo_decompress_threadfn,
+ data[thr].thr = kthread_run(decompress_threadfn,
&data[thr],
"image_decompress/%u", thr);
if (IS_ERR(data[thr].thr)) {
@@ -1262,18 +1262,18 @@ static int load_image_lzo(struct swap_map_handle *handle,
*/
if (low_free_pages() > snapshot_get_image_size())
read_pages = (low_free_pages() - snapshot_get_image_size()) / 2;
- read_pages = clamp_val(read_pages, LZO_MIN_RD_PAGES, LZO_MAX_RD_PAGES);
+ read_pages = clamp_val(read_pages, CMP_MIN_RD_PAGES, CMP_MAX_RD_PAGES);

for (i = 0; i < read_pages; i++) {
- page[i] = (void *)__get_free_page(i < LZO_CMP_PAGES ?
+ page[i] = (void *)__get_free_page(i < CMP_PAGES ?
GFP_NOIO | __GFP_HIGH :
GFP_NOIO | __GFP_NOWARN |
__GFP_NORETRY);

if (!page[i]) {
- if (i < LZO_CMP_PAGES) {
+ if (i < CMP_PAGES) {
ring_size = i;
- pr_err("Failed to allocate LZO pages\n");
+ pr_err("Failed to allocate compression pages\n");
ret = -ENOMEM;
goto out_clean;
} else {
@@ -1344,13 +1344,13 @@ static int load_image_lzo(struct swap_map_handle *handle,
data[thr].cmp_len = *(size_t *)page[pg];
if (unlikely(!data[thr].cmp_len ||
data[thr].cmp_len >
- lzo1x_worst_compress(LZO_UNC_SIZE))) {
- pr_err("Invalid LZO compressed length\n");
+ lzo1x_worst_compress(UNC_SIZE))) {
+ pr_err("Invalid compressed length\n");
ret = -1;
goto out_finish;
}

- need = DIV_ROUND_UP(data[thr].cmp_len + LZO_HEADER,
+ need = DIV_ROUND_UP(data[thr].cmp_len + CMP_HEADER,
PAGE_SIZE);
if (need > have) {
if (eof > 1) {
@@ -1361,7 +1361,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
}

for (off = 0;
- off < LZO_HEADER + data[thr].cmp_len;
+ off < CMP_HEADER + data[thr].cmp_len;
off += PAGE_SIZE) {
memcpy(data[thr].cmp + off,
page[pg], PAGE_SIZE);
@@ -1378,7 +1378,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
/*
* Wait for more data while we are decompressing.
*/
- if (have < LZO_CMP_PAGES && asked) {
+ if (have < CMP_PAGES && asked) {
ret = hib_wait_io(&hb);
if (ret)
goto out_finish;
@@ -1396,14 +1396,14 @@ static int load_image_lzo(struct swap_map_handle *handle,
ret = data[thr].ret;

if (ret < 0) {
- pr_err("LZO decompression failed\n");
+ pr_err("decompression failed\n");
goto out_finish;
}

if (unlikely(!data[thr].unc_len ||
- data[thr].unc_len > LZO_UNC_SIZE ||
- data[thr].unc_len & (PAGE_SIZE - 1))) {
- pr_err("Invalid LZO uncompressed length\n");
+ data[thr].unc_len > UNC_SIZE ||
+ data[thr].unc_len & (PAGE_SIZE - 1))) {
+ pr_err("Invalid uncompressed length\n");
ret = -1;
goto out_finish;
}
@@ -1500,7 +1500,7 @@ int swsusp_read(unsigned int *flags_p)
if (!error) {
error = (*flags_p & SF_NOCOMPRESS_MODE) ?
load_image(&handle, &snapshot, header->pages - 1) :
- load_image_lzo(&handle, &snapshot, header->pages - 1);
+ load_compressed_image(&handle, &snapshot, header->pages - 1);
}
swap_reader_finish(&handle);
end:
--
2.17.1

2023-11-15 12:23:35

by Nikhil V

[permalink] [raw]
Subject: [PATCH RESEND v2 2/4] PM: hibernate: Move to crypto APIs for LZO compression

Currently for hibernation, LZO is the only compression algorithm
available and uses the existing LZO library calls. However, there
is no flexibility to switch to other algorithms which provides better
results. The main idea is that different compression algorithms have
different characteristics and hibernation may benefit when it uses
alternate algorithms.

By moving to crypto based APIs, it lays a foundation to use other
compression algorithms for hibernation. There are no functional changes
introduced by this approach.

Signed-off-by: Nikhil V <[email protected]>
---
kernel/power/Kconfig | 21 +++++++-
kernel/power/hibernate.c | 33 +++++++++++++
kernel/power/power.h | 5 ++
kernel/power/swap.c | 101 +++++++++++++++++++++++++++++----------
4 files changed, 132 insertions(+), 28 deletions(-)

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 4b31629c5be4..d4167159bae8 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -39,9 +39,9 @@ config HIBERNATION
bool "Hibernation (aka 'suspend to disk')"
depends on SWAP && ARCH_HIBERNATION_POSSIBLE
select HIBERNATE_CALLBACKS
- select LZO_COMPRESS
- select LZO_DECOMPRESS
select CRC32
+ select CRYPTO
+ select CRYPTO_LZO
help
Enable the suspend to disk (STD) functionality, which is usually
called "hibernation" in user interfaces. STD checkpoints the
@@ -92,6 +92,23 @@ config HIBERNATION_SNAPSHOT_DEV

If in doubt, say Y.

+choice
+ prompt "Default compressor"
+ default HIBERNATION_COMP_LZO
+ depends on HIBERNATION
+
+config HIBERNATION_COMP_LZO
+ bool "lzo"
+ depends on CRYPTO_LZO
+
+endchoice
+
+config HIBERNATION_DEF_COMP
+ string
+ default "lzo" if HIBERNATION_COMP_LZO
+ help
+ Default compressor to be used for hibernation.
+
config PM_STD_PARTITION
string "Default resume partition"
depends on HIBERNATION
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index dee341ae4ace..fe0a3c5b8cfe 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -47,6 +47,15 @@ dev_t swsusp_resume_device;
sector_t swsusp_resume_block;
__visible int in_suspend __nosavedata;

+static const char *default_compressor = CONFIG_HIBERNATION_DEF_COMP;
+
+/*
+ * Compression/decompression algorithm to be used while saving/loading
+ * image to/from disk. This would later be used in 'kernel/power/swap.c'
+ * to allocate comp streams.
+ */
+char hib_comp_algo[CRYPTO_MAX_ALG_NAME];
+
enum {
HIBERNATION_INVALID,
HIBERNATION_PLATFORM,
@@ -726,6 +735,17 @@ int hibernate(void)
return -EPERM;
}

+ /*
+ * Query for the compression algorithm support if compression is enabled.
+ */
+ if (!nocompress) {
+ strscpy(hib_comp_algo, default_compressor, sizeof(hib_comp_algo));
+ if (crypto_has_comp(hib_comp_algo, 0, 0) != 1) {
+ pr_err("%s compression is not available\n", hib_comp_algo);
+ return -EOPNOTSUPP;
+ }
+ }
+
sleep_flags = lock_system_sleep();
/* The snapshot device should not be opened while we're running */
if (!hibernate_acquire()) {
@@ -949,6 +969,19 @@ static int software_resume(void)
if (error)
goto Unlock;

+ /*
+ * Check if the hibernation image is compressed. If so, query for
+ * the algorithm support.
+ */
+ if (!(swsusp_header_flags & SF_NOCOMPRESS_MODE)) {
+ strscpy(hib_comp_algo, default_compressor, sizeof(hib_comp_algo));
+ if (crypto_has_comp(hib_comp_algo, 0, 0) != 1) {
+ pr_err("%s compression is not available\n", hib_comp_algo);
+ error = -EOPNOTSUPP;
+ goto Unlock;
+ }
+ }
+
/* The snapshot device should not be opened while we're running */
if (!hibernate_acquire()) {
error = -EBUSY;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 17fd9aaaf084..88836e627512 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -6,6 +6,7 @@
#include <linux/compiler.h>
#include <linux/cpu.h>
#include <linux/cpuidle.h>
+#include <linux/crypto.h>

struct swsusp_info {
struct new_utsname uts;
@@ -54,6 +55,10 @@ asmlinkage int swsusp_save(void);

/* kernel/power/hibernate.c */
extern bool freezer_test_done;
+extern char hib_comp_algo[CRYPTO_MAX_ALG_NAME];
+
+/* kernel/power/swap.c */
+extern unsigned int swsusp_header_flags;

extern int hibernation_snapshot(int platform_mode);
extern int hibernation_restore(int platform_mode);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 765700f52978..5d2c155d97cc 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -23,7 +23,6 @@
#include <linux/swapops.h>
#include <linux/pm.h>
#include <linux/slab.h>
-#include <linux/lzo.h>
#include <linux/vmalloc.h>
#include <linux/cpumask.h>
#include <linux/atomic.h>
@@ -339,6 +338,13 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
return error;
}

+/*
+ * Hold the swsusp_header flag. This is used in software_resume() in
+ * 'kernel/power/hibernate' to check if the image is compressed and query
+ * for the compression algorithm support(if so).
+ */
+unsigned int swsusp_header_flags;
+
/**
* swsusp_swap_check - check if the resume device is a swap device
* and get its index (if so)
@@ -514,6 +520,12 @@ static int swap_writer_finish(struct swap_map_handle *handle,
return error;
}

+/*
+ * Bytes we need for compressed data in worst case. We assume(limitation)
+ * this is the worst of all the compression algorithms.
+ */
+#define bytes_worst_compress(x) ((x) + ((x) / 16) + 64 + 3 + 2)
+
/* We need to remember how much compressed data we need to read. */
#define CMP_HEADER sizeof(size_t)

@@ -522,7 +534,7 @@ static int swap_writer_finish(struct swap_map_handle *handle,
#define UNC_SIZE (UNC_PAGES * PAGE_SIZE)

/* Number of pages we need for compressed data (worst case). */
-#define CMP_PAGES DIV_ROUND_UP(lzo1x_worst_compress(UNC_SIZE) + \
+#define CMP_PAGES DIV_ROUND_UP(bytes_worst_compress(UNC_SIZE) + \
CMP_HEADER, PAGE_SIZE)
#define CMP_SIZE (CMP_PAGES * PAGE_SIZE)

@@ -533,7 +545,6 @@ static int swap_writer_finish(struct swap_map_handle *handle,
#define CMP_MIN_RD_PAGES 1024
#define CMP_MAX_RD_PAGES 8192

-
/**
* save_image - save the suspend image data
*/
@@ -629,6 +640,7 @@ static int crc32_threadfn(void *data)
*/
struct cmp_data {
struct task_struct *thr; /* thread */
+ struct crypto_comp *cc; /* crypto compressor stream */
atomic_t ready; /* ready to start flag */
atomic_t stop; /* ready to stop flag */
int ret; /* return code */
@@ -638,15 +650,18 @@ struct cmp_data {
size_t cmp_len; /* compressed length */
unsigned char unc[UNC_SIZE]; /* uncompressed buffer */
unsigned char cmp[CMP_SIZE]; /* compressed buffer */
- unsigned char wrk[LZO1X_1_MEM_COMPRESS]; /* compression workspace */
};

+/* Indicates the image size after compression */
+static atomic_t compressed_size = ATOMIC_INIT(0);
+
/*
* Compression function that runs in its own thread.
*/
static int compress_threadfn(void *data)
{
struct cmp_data *d = data;
+ unsigned int cmp_len = 0;

while (1) {
wait_event(d->go, atomic_read(&d->ready) ||
@@ -660,9 +675,13 @@ static int compress_threadfn(void *data)
}
atomic_set(&d->ready, 0);

- d->ret = lzo1x_1_compress(d->unc, d->unc_len,
- d->cmp + CMP_HEADER, &d->cmp_len,
- d->wrk);
+ cmp_len = CMP_SIZE - CMP_HEADER;
+ d->ret = crypto_comp_compress(d->cc, d->unc, d->unc_len,
+ d->cmp + CMP_HEADER,
+ &cmp_len);
+ d->cmp_len = cmp_len;
+
+ atomic_set(&compressed_size, atomic_read(&compressed_size) + d->cmp_len);
atomic_set(&d->stop, 1);
wake_up(&d->done);
}
@@ -694,6 +713,8 @@ static int save_compressed_image(struct swap_map_handle *handle,

hib_init_batch(&hb);

+ atomic_set(&compressed_size, 0);
+
/*
* We'll limit the number of threads for compression to limit memory
* footprint.
@@ -703,14 +724,14 @@ static int save_compressed_image(struct swap_map_handle *handle,

page = (void *)__get_free_page(GFP_NOIO | __GFP_HIGH);
if (!page) {
- pr_err("Failed to allocate compression page\n");
+ pr_err("Failed to allocate %s page\n", hib_comp_algo);
ret = -ENOMEM;
goto out_clean;
}

data = vzalloc(array_size(nr_threads, sizeof(*data)));
if (!data) {
- pr_err("Failed to allocate compression data\n");
+ pr_err("Failed to allocate %s data\n", hib_comp_algo);
ret = -ENOMEM;
goto out_clean;
}
@@ -729,6 +750,13 @@ static int save_compressed_image(struct swap_map_handle *handle,
init_waitqueue_head(&data[thr].go);
init_waitqueue_head(&data[thr].done);

+ data[thr].cc = crypto_alloc_comp(hib_comp_algo, 0, 0);
+ if (IS_ERR_OR_NULL(data[thr].cc)) {
+ pr_err("Could not allocate comp stream %ld\n", PTR_ERR(data[thr].cc));
+ ret = -EFAULT;
+ goto out_clean;
+ }
+
data[thr].thr = kthread_run(compress_threadfn,
&data[thr],
"image_compress/%u", thr);
@@ -767,7 +795,7 @@ static int save_compressed_image(struct swap_map_handle *handle,
*/
handle->reqd_free_pages = reqd_free_pages();

- pr_info("Using %u thread(s) for compression\n", nr_threads);
+ pr_info("Using %u thread(s) for %s compression\n", nr_threads, hib_comp_algo);
pr_info("Compressing and saving image data (%u pages)...\n",
nr_to_write);
m = nr_to_write / 10;
@@ -817,14 +845,14 @@ static int save_compressed_image(struct swap_map_handle *handle,
ret = data[thr].ret;

if (ret < 0) {
- pr_err("compression failed\n");
+ pr_err("%s compression failed\n", hib_comp_algo);
goto out_finish;
}

if (unlikely(!data[thr].cmp_len ||
data[thr].cmp_len >
- lzo1x_worst_compress(data[thr].unc_len))) {
- pr_err("Invalid compressed length\n");
+ bytes_worst_compress(data[thr].unc_len))) {
+ pr_err("Invalid %s compressed length\n", hib_comp_algo);
ret = -1;
goto out_finish;
}
@@ -862,6 +890,9 @@ static int save_compressed_image(struct swap_map_handle *handle,
if (!ret)
pr_info("Image saving done\n");
swsusp_show_speed(start, stop, nr_to_write, "Wrote");
+ pr_info("Image size after compression: %d kbytes\n",
+ (atomic_read(&compressed_size) / 1024));
+
out_clean:
hib_finish_batch(&hb);
if (crc) {
@@ -870,9 +901,12 @@ static int save_compressed_image(struct swap_map_handle *handle,
kfree(crc);
}
if (data) {
- for (thr = 0; thr < nr_threads; thr++)
+ for (thr = 0; thr < nr_threads; thr++) {
if (data[thr].thr)
kthread_stop(data[thr].thr);
+ if (data[thr].cc)
+ crypto_free_comp(data[thr].cc);
+ }
vfree(data);
}
if (page) free_page((unsigned long)page);
@@ -1113,6 +1147,7 @@ static int load_image(struct swap_map_handle *handle,
*/
struct dec_data {
struct task_struct *thr; /* thread */
+ struct crypto_comp *cc; /* crypto compressor stream */
atomic_t ready; /* ready to start flag */
atomic_t stop; /* ready to stop flag */
int ret; /* return code */
@@ -1130,6 +1165,7 @@ struct dec_data {
static int decompress_threadfn(void *data)
{
struct dec_data *d = data;
+ unsigned int unc_len = 0;

while (1) {
wait_event(d->go, atomic_read(&d->ready) ||
@@ -1143,9 +1179,11 @@ static int decompress_threadfn(void *data)
}
atomic_set(&d->ready, 0);

- d->unc_len = UNC_SIZE;
- d->ret = lzo1x_decompress_safe(d->cmp + CMP_HEADER, d->cmp_len,
- d->unc, &d->unc_len);
+ unc_len = UNC_SIZE;
+ d->ret = crypto_comp_decompress(d->cc, d->cmp + CMP_HEADER, d->cmp_len,
+ d->unc, &unc_len);
+ d->unc_len = unc_len;
+
if (clean_pages_on_decompress)
flush_icache_range((unsigned long)d->unc,
(unsigned long)d->unc + d->unc_len);
@@ -1193,14 +1231,14 @@ static int load_compressed_image(struct swap_map_handle *handle,

page = vmalloc(array_size(CMP_MAX_RD_PAGES, sizeof(*page)));
if (!page) {
- pr_err("Failed to allocate compression page\n");
+ pr_err("Failed to allocate %s page\n", hib_comp_algo);
ret = -ENOMEM;
goto out_clean;
}

data = vzalloc(array_size(nr_threads, sizeof(*data)));
if (!data) {
- pr_err("Failed to allocate compression data\n");
+ pr_err("Failed to allocate %s data\n", hib_comp_algo);
ret = -ENOMEM;
goto out_clean;
}
@@ -1221,6 +1259,13 @@ static int load_compressed_image(struct swap_map_handle *handle,
init_waitqueue_head(&data[thr].go);
init_waitqueue_head(&data[thr].done);

+ data[thr].cc = crypto_alloc_comp(hib_comp_algo, 0, 0);
+ if (IS_ERR_OR_NULL(data[thr].cc)) {
+ pr_err("Could not allocate comp stream %ld\n", PTR_ERR(data[thr].cc));
+ ret = -EFAULT;
+ goto out_clean;
+ }
+
data[thr].thr = kthread_run(decompress_threadfn,
&data[thr],
"image_decompress/%u", thr);
@@ -1273,7 +1318,7 @@ static int load_compressed_image(struct swap_map_handle *handle,
if (!page[i]) {
if (i < CMP_PAGES) {
ring_size = i;
- pr_err("Failed to allocate compression pages\n");
+ pr_err("Failed to allocate %s pages\n", hib_comp_algo);
ret = -ENOMEM;
goto out_clean;
} else {
@@ -1283,7 +1328,7 @@ static int load_compressed_image(struct swap_map_handle *handle,
}
want = ring_size = i;

- pr_info("Using %u thread(s) for decompression\n", nr_threads);
+ pr_info("Using %u thread(s) for %s decompression\n", nr_threads, hib_comp_algo);
pr_info("Loading and decompressing image data (%u pages)...\n",
nr_to_read);
m = nr_to_read / 10;
@@ -1344,8 +1389,8 @@ static int load_compressed_image(struct swap_map_handle *handle,
data[thr].cmp_len = *(size_t *)page[pg];
if (unlikely(!data[thr].cmp_len ||
data[thr].cmp_len >
- lzo1x_worst_compress(UNC_SIZE))) {
- pr_err("Invalid compressed length\n");
+ bytes_worst_compress(UNC_SIZE))) {
+ pr_err("Invalid %s compressed length\n", hib_comp_algo);
ret = -1;
goto out_finish;
}
@@ -1396,14 +1441,14 @@ static int load_compressed_image(struct swap_map_handle *handle,
ret = data[thr].ret;

if (ret < 0) {
- pr_err("decompression failed\n");
+ pr_err("%s decompression failed\n", hib_comp_algo);
goto out_finish;
}

if (unlikely(!data[thr].unc_len ||
data[thr].unc_len > UNC_SIZE ||
data[thr].unc_len & (PAGE_SIZE - 1))) {
- pr_err("Invalid uncompressed length\n");
+ pr_err("Invalid %s uncompressed length\n", hib_comp_algo);
ret = -1;
goto out_finish;
}
@@ -1464,9 +1509,12 @@ static int load_compressed_image(struct swap_map_handle *handle,
kfree(crc);
}
if (data) {
- for (thr = 0; thr < nr_threads; thr++)
+ for (thr = 0; thr < nr_threads; thr++) {
if (data[thr].thr)
kthread_stop(data[thr].thr);
+ if (data[thr].cc)
+ crypto_free_comp(data[thr].cc);
+ }
vfree(data);
}
vfree(page);
@@ -1535,6 +1583,7 @@ int swsusp_check(bool exclusive)

if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) {
memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
+ swsusp_header_flags = swsusp_header->flags;
/* Reset swap signature now */
error = hib_submit_io(REQ_OP_WRITE | REQ_SYNC,
swsusp_resume_block,
--
2.17.1

2023-11-15 12:23:48

by Nikhil V

[permalink] [raw]
Subject: [PATCH RESEND v2 3/4] PM: hibernate: Add support for LZ4 compression for hibernation

Extend the support for LZ4 compression to be used with hibernation.
The main idea is that different compression algorithms
have different characteristics and hibernation may benefit when it uses
any of these algorithms: a default algorithm, having higher
compression rate but is slower(compression/decompression) and a
secondary algorithm, that is faster(compression/decompression) but has
lower compression rate.

LZ4 algorithm has better decompression speeds over LZO. This reduces
the hibernation image restore time.
As per test results:
LZO LZ4
Size before Compression(bytes) 682696704 682393600
Size after Compression(bytes) 146502402 155993547
Decompression Rate 335.02 MB/s 501.05 MB/s
Restore time 4.4s 3.8s

LZO is the default compression algorithm used for hibernation. Enable
CONFIG_HIBERNATION_COMP_LZ4 to set the default compressor as LZ4.

Signed-off-by: Nikhil V <[email protected]>
---
kernel/power/Kconfig | 5 +++++
kernel/power/hibernate.c | 25 ++++++++++++++++++++++---
kernel/power/power.h | 14 ++++++++++++++
3 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index d4167159bae8..afce8130d8b9 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -101,11 +101,16 @@ config HIBERNATION_COMP_LZO
bool "lzo"
depends on CRYPTO_LZO

+config HIBERNATION_COMP_LZ4
+ bool "lz4"
+ depends on CRYPTO_LZ4
+
endchoice

config HIBERNATION_DEF_COMP
string
default "lzo" if HIBERNATION_COMP_LZO
+ default "lz4" if HIBERNATION_COMP_LZ4
help
Default compressor to be used for hibernation.

diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index fe0a3c5b8cfe..274327232dab 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -721,6 +721,9 @@ static int load_image_and_restore(void)
return error;
}

+#define COMPRESSION_ALGO_LZO "lzo"
+#define COMPRESSION_ALGO_LZ4 "lz4"
+
/**
* hibernate - Carry out system hibernation, including saving the image.
*/
@@ -780,11 +783,24 @@ int hibernate(void)

if (hibernation_mode == HIBERNATION_PLATFORM)
flags |= SF_PLATFORM_MODE;
- if (nocompress)
+ if (nocompress) {
flags |= SF_NOCOMPRESS_MODE;
- else
+ } else {
flags |= SF_CRC32_MODE;

+ /*
+ * By default, LZO compression is enabled. Use SF_COMPRESSION_ALG_LZ4
+ * to override this behaviour and use LZ4.
+ *
+ * Refer kernel/power/power.h for more details
+ */
+
+ if (!strcmp(hib_comp_algo, COMPRESSION_ALGO_LZ4))
+ flags |= SF_COMPRESSION_ALG_LZ4;
+ else
+ flags |= SF_COMPRESSION_ALG_LZO;
+ }
+
pm_pr_dbg("Writing hibernation image.\n");
error = swsusp_write(flags);
swsusp_free();
@@ -974,7 +990,10 @@ static int software_resume(void)
* the algorithm support.
*/
if (!(swsusp_header_flags & SF_NOCOMPRESS_MODE)) {
- strscpy(hib_comp_algo, default_compressor, sizeof(hib_comp_algo));
+ if (swsusp_header_flags & SF_COMPRESSION_ALG_LZ4)
+ strscpy(hib_comp_algo, COMPRESSION_ALGO_LZ4, sizeof(hib_comp_algo));
+ else
+ strscpy(hib_comp_algo, default_compressor, sizeof(hib_comp_algo));
if (crypto_has_comp(hib_comp_algo, 0, 0) != 1) {
pr_err("%s compression is not available\n", hib_comp_algo);
error = -EOPNOTSUPP;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 88836e627512..7baeba100da5 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -167,11 +167,25 @@ extern int swsusp_swap_in_use(void);
* Flags that can be passed from the hibernatig hernel to the "boot" kernel in
* the image header.
*/
+#define SF_COMPRESSION_ALG_LZO 0 /* dummy, details given below */
#define SF_PLATFORM_MODE 1
#define SF_NOCOMPRESS_MODE 2
#define SF_CRC32_MODE 4
#define SF_HW_SIG 8

+/*
+ * Bit to indicate the compression algorithm to be used(for LZ4). The same
+ * could be checked while saving/loading image to/from disk to use the
+ * corresponding algorithms.
+ *
+ * By default, LZO compression is enabled if SF_CRC32_MODE is set. Use
+ * SF_COMPRESSION_ALG_LZ4 to override this behaviour and use LZ4.
+ *
+ * SF_CRC32_MODE, SF_COMPRESSION_ALG_LZO(dummy) -> Compression, LZO
+ * SF_CRC32_MODE, SF_COMPRESSION_ALG_LZ4 -> Compression, LZ4
+ */
+#define SF_COMPRESSION_ALG_LZ4 16
+
/* kernel/power/hibernate.c */
int swsusp_check(bool exclusive);
extern void swsusp_free(void);
--
2.17.1

2023-11-15 12:24:03

by Nikhil V

[permalink] [raw]
Subject: [PATCH RESEND v2 4/4] PM: hibernate: Support to select compression algorithm

Currently the default compression algorithm is selected based on
Kconfig. Introduce a kernel command line parameter "hib_compression" to
override this behaviour.

Different compression algorithms have different characteristics and
hibernation may benefit when it uses any of these algorithms, especially
when a secondary algorithm offers better decompression speeds over a
default algorithm, which in turn reduces hibernation image restore time.

Users can set "hib_compression" command line parameter to override the
default algorithm. Currently LZO and LZ4 are the supported algorithms.
Usage:
LZO: hib_compression=lzo
LZ4: hib_compression=lz4

LZO is the default compression algorithm used with hibernation.

Signed-off-by: Nikhil V <[email protected]>
---
.../admin-guide/kernel-parameters.txt | 6 ++++
kernel/power/hibernate.c | 31 ++++++++++++++++++-
2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 65731b060e3f..4acc2d95030a 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1735,6 +1735,12 @@
(that will set all pages holding image data
during restoration read-only).

+ hib_compression= [COMPRESSION ALGORITHM]
+ lzo Select LZO compression algorithm to compress/decompress
+ hibernation images.
+ lz4 Select LZ4 compression algorithm to compress/decompress
+ hibernation images.
+
highmem=nn[KMG] [KNL,BOOT] forces the highmem zone to have an exact
size of <nn>. This works even on boxes that have no
highmem otherwise. This also works to reduce highmem
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 274327232dab..721a9e3e0c9a 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -742,7 +742,8 @@ int hibernate(void)
* Query for the compression algorithm support if compression is enabled.
*/
if (!nocompress) {
- strscpy(hib_comp_algo, default_compressor, sizeof(hib_comp_algo));
+ if (!hib_comp_algo[0])
+ strscpy(hib_comp_algo, default_compressor, sizeof(hib_comp_algo));
if (crypto_has_comp(hib_comp_algo, 0, 0) != 1) {
pr_err("%s compression is not available\n", hib_comp_algo);
return -EOPNOTSUPP;
@@ -1416,6 +1417,33 @@ static int __init nohibernate_setup(char *str)
return 1;
}

+static const char * const comp_alg_enabled[] = {
+#if IS_ENABLED(CONFIG_CRYPTO_LZO)
+ COMPRESSION_ALGO_LZO,
+#endif
+#if IS_ENABLED(CONFIG_CRYPTO_LZ4)
+ COMPRESSION_ALGO_LZ4,
+#endif
+};
+
+static int __init compression_setup(char *str)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(comp_alg_enabled); i++) {
+ if (!strcmp(str, comp_alg_enabled[i])) {
+ strscpy(hib_comp_algo, str, sizeof(hib_comp_algo));
+ goto setup_done;
+ }
+ }
+ pr_info("Cannot set specified compressor. Falling back to %s\n",
+ default_compressor);
+ strscpy(hib_comp_algo, default_compressor, sizeof(hib_comp_algo));
+
+setup_done:
+ return 1;
+}
+
__setup("noresume", noresume_setup);
__setup("resume_offset=", resume_offset_setup);
__setup("resume=", resume_setup);
@@ -1423,3 +1451,4 @@ __setup("hibernate=", hibernate_setup);
__setup("resumewait", resumewait_setup);
__setup("resumedelay=", resumedelay_setup);
__setup("nohibernate", nohibernate_setup);
+__setup("hib_compression=", compression_setup);
--
2.17.1

2023-11-29 10:20:29

by Nikhil V

[permalink] [raw]
Subject: Re: [PATCH RESEND v2 0/4] PM: hibernate: LZ4 compression support



On 11/15/2023 5:52 PM, Nikhil V wrote:
> This patch series covers the following:
> 1. Renaming lzo* to generic names, except for lzo_xxx() APIs. This is
> used in the next patch where we move to crypto based APIs for
> compression. There are no functional changes introduced by this
> approach.
>
>
> 2. Replace LZO library calls with crypto generic APIs
>
> Currently for hibernation, LZO is the only compression algorithm
> available and uses the existing LZO library calls. However, there
> is no flexibility to switch to other algorithms which provides better
> results. The main idea is that different compression algorithms have
> different characteristics and hibernation may benefit when it uses
> alternate algorithms.
>
> By moving to crypto based APIs, it lays a foundation to use other
> compression algorithms for hibernation.
>
>
> 3. LZ4 compression
>
> Extend the support for LZ4 compression to be used with hibernation.
> The main idea is that different compression algorithms have different
> characteristics and hibernation may benefit when it uses any of these
> algorithms: a default algorithm, having higher compression rate but is
> slower(compression/decompression) and a secondary algorithm, that is
> faster(compression/decompression) but has lower compression rate.
>
> LZ4 algorithm has better decompression speeds over LZO. This reduces
> the hibernation image restore time.
> As per test results:
> LZO LZ4
> Size before Compression(bytes) 682696704 682393600
> Size after Compression(bytes) 146502402 155993547
> Decompression Rate 335.02 MB/s 501.05 MB/s
> Restore time 4.4s 3.8s
>
> LZO is the default compression algorithm used for hibernation. Enable
> CONFIG_HIBERNATION_DEF_COMP_LZ4 to set the default compressor as LZ4.
>
> Compression Benchmarks: https://github.com/lz4/lz4
>
>
> 4. Support to select compression algorithm
>
> Currently the default compression algorithm is selected based on
> Kconfig. Introduce a kernel command line parameter "hib_compression" to
> override this behaviour.
>
> Users can set "hib_compression" command line parameter to specify
> the algorithm.
> Usage:
> LZO: hib_compression=lzo
> LZ4: hib_compression=lz4
> LZO is the default compression algorithm used with hibernation.
>
>
> Changes in v2:
> - Fixed build issues reported by kernel test robot for ARCH=sh, [1].
> [1] https://lore.kernel.org/oe-kbuild-all/[email protected]/
>
> Nikhil V (4):
> PM: hibernate: Rename lzo* to make it generic
> PM: hibernate: Move to crypto APIs for LZO compression
> PM: hibernate: Add support for LZ4 compression for hibernation
> PM: hibernate: Support to select compression algorithm
>
> .../admin-guide/kernel-parameters.txt | 6 +
> kernel/power/Kconfig | 26 ++-
> kernel/power/hibernate.c | 85 +++++++-
> kernel/power/power.h | 19 ++
> kernel/power/swap.c | 189 +++++++++++-------
> 5 files changed, 251 insertions(+), 74 deletions(-)
>
>
> base-commit: b85ea95d086471afb4ad062012a4d73cd328fa86

Hi @Rafael/@Pavel/@Len,

Could you please let me know if you have any concerns on this approach?

FYI: We have tested this on QEMU and its working fine.

Logs(suspend):
[ 75.242227] PM: Using 3 thread(s) for lz4 compression
[ 75.243043] PM: Compressing and saving image data (17495 pages)...
[ 75.243917] PM: Image saving progress: 0%
[ 75.261727] PM: Image saving progress: 10%
[ 75.277968] PM: Image saving progress: 20%
[ 75.290927] PM: Image saving progress: 30%
[ 75.305186] PM: Image saving progress: 40%
[ 75.318252] PM: Image saving progress: 50%
[ 75.330310] PM: Image saving progress: 60%
[ 75.345906] PM: Image saving progress: 70%
[ 75.359054] PM: Image saving progress: 80%
[ 75.372176] PM: Image saving progress: 90%
[ 75.388411] PM: Image saving progress: 100%
[ 75.389775] PM: Image saving done
[ 75.390397] PM: hibernation: Wrote 69980 kbytes in 0.14 seconds
(499.85 MB/s)
[ 75.391591] PM: Image size after compression: 28242 kbytes
[ 75.393089] PM: S|
[ 75.399784] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 75.439170] sd 0:0:0:0: [sda] Stopping disk
[ 75.501461] ACPI: PM: Preparing to enter system sleep state S5
[ 75.502766] reboot: Power down



Logs(resume):
[ 1.063248] PM: hibernation: resume from hibernation
[ 1.072868] Freezing user space processes
[ 1.073707] Freezing user space processes completed (elapsed 0.000
seconds)
[ 1.075192] OOM killer disabled.
[ 1.075837] Freezing remaining freezable tasks
[ 1.078010] Freezing remaining freezable tasks completed (elapsed
0.001 seconds)
[ 1.087489] PM: Using 3 thread(s) for lz4 decompression
[ 1.088570] PM: Loading and decompressing image data (17495 pages)...
[ 1.125549] PM: Image loading progress: 0%
[ 1.190380] PM: Image loading progress: 10%
[ 1.204963] PM: Image loading progress: 20%
[ 1.218988] PM: Image loading progress: 30%
[ 1.233697] PM: Image loading progress: 40%
[ 1.248658] PM: Image loading progress: 50%
[ 1.262910] PM: Image loading progress: 60%
[ 1.276966] PM: Image loading progress: 70%
[ 1.290517] PM: Image loading progress: 80%
[ 1.305427] PM: Image loading progress: 90%
[ 1.320666] PM: Image loading progress: 100%
[ 1.321866] PM: Image loading done
[ 1.322599] PM: hibernation: Read 69980 kbytes in 0.23 seconds
(304.26 MB/s)
[ 1.324795] printk: Suspending console(s) (use no_console_suspend to
debug)
[ 74.943801] ata1.00: Entering standby power mode


Thanks,
Nikhil V

2023-12-12 12:44:45

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH RESEND v2 0/4] PM: hibernate: LZ4 compression support

Hi,

On Wed, Nov 29, 2023 at 11:20 AM Nikhil V <[email protected]> wrote:
>
>
> On 11/15/2023 5:52 PM, Nikhil V wrote:
> > This patch series covers the following:
> > 1. Renaming lzo* to generic names, except for lzo_xxx() APIs. This is
> > used in the next patch where we move to crypto based APIs for
> > compression. There are no functional changes introduced by this
> > approach.
> >
> >
> > 2. Replace LZO library calls with crypto generic APIs
> >
> > Currently for hibernation, LZO is the only compression algorithm
> > available and uses the existing LZO library calls. However, there
> > is no flexibility to switch to other algorithms which provides better
> > results. The main idea is that different compression algorithms have
> > different characteristics and hibernation may benefit when it uses
> > alternate algorithms.
> >
> > By moving to crypto based APIs, it lays a foundation to use other
> > compression algorithms for hibernation.
> >
> >
> > 3. LZ4 compression
> >
> > Extend the support for LZ4 compression to be used with hibernation.
> > The main idea is that different compression algorithms have different
> > characteristics and hibernation may benefit when it uses any of these
> > algorithms: a default algorithm, having higher compression rate but is
> > slower(compression/decompression) and a secondary algorithm, that is
> > faster(compression/decompression) but has lower compression rate.
> >
> > LZ4 algorithm has better decompression speeds over LZO. This reduces
> > the hibernation image restore time.
> > As per test results:
> > LZO LZ4
> > Size before Compression(bytes) 682696704 682393600
> > Size after Compression(bytes) 146502402 155993547
> > Decompression Rate 335.02 MB/s 501.05 MB/s
> > Restore time 4.4s 3.8s
> >
> > LZO is the default compression algorithm used for hibernation. Enable
> > CONFIG_HIBERNATION_DEF_COMP_LZ4 to set the default compressor as LZ4.
> >
> > Compression Benchmarks: https://github.com/lz4/lz4
> >
> >
> > 4. Support to select compression algorithm
> >
> > Currently the default compression algorithm is selected based on
> > Kconfig. Introduce a kernel command line parameter "hib_compression" to
> > override this behaviour.
> >
> > Users can set "hib_compression" command line parameter to specify
> > the algorithm.
> > Usage:
> > LZO: hib_compression=lzo
> > LZ4: hib_compression=lz4
> > LZO is the default compression algorithm used with hibernation.
> >
> >
> > Changes in v2:
> > - Fixed build issues reported by kernel test robot for ARCH=sh, [1].
> > [1] https://lore.kernel.org/oe-kbuild-all/[email protected]/
> >
> > Nikhil V (4):
> > PM: hibernate: Rename lzo* to make it generic
> > PM: hibernate: Move to crypto APIs for LZO compression
> > PM: hibernate: Add support for LZ4 compression for hibernation
> > PM: hibernate: Support to select compression algorithm
> >
> > .../admin-guide/kernel-parameters.txt | 6 +
> > kernel/power/Kconfig | 26 ++-
> > kernel/power/hibernate.c | 85 +++++++-
> > kernel/power/power.h | 19 ++
> > kernel/power/swap.c | 189 +++++++++++-------
> > 5 files changed, 251 insertions(+), 74 deletions(-)
> >
> >
> > base-commit: b85ea95d086471afb4ad062012a4d73cd328fa86
>
> Hi @Rafael/@Pavel/@Len,
>
> Could you please let me know if you have any concerns on this approach?

Not really a concern, but that is a significant change that I would
rather make early in the cycle, which means after the 6.8 merge
window.

No need to resend unless there is something to address in which case
I'll let you know.

Thanks!

> FYI: We have tested this on QEMU and its working fine.
>
> Logs(suspend):
> [ 75.242227] PM: Using 3 thread(s) for lz4 compression
> [ 75.243043] PM: Compressing and saving image data (17495 pages)...
> [ 75.243917] PM: Image saving progress: 0%
> [ 75.261727] PM: Image saving progress: 10%
> [ 75.277968] PM: Image saving progress: 20%
> [ 75.290927] PM: Image saving progress: 30%
> [ 75.305186] PM: Image saving progress: 40%
> [ 75.318252] PM: Image saving progress: 50%
> [ 75.330310] PM: Image saving progress: 60%
> [ 75.345906] PM: Image saving progress: 70%
> [ 75.359054] PM: Image saving progress: 80%
> [ 75.372176] PM: Image saving progress: 90%
> [ 75.388411] PM: Image saving progress: 100%
> [ 75.389775] PM: Image saving done
> [ 75.390397] PM: hibernation: Wrote 69980 kbytes in 0.14 seconds
> (499.85 MB/s)
> [ 75.391591] PM: Image size after compression: 28242 kbytes
> [ 75.393089] PM: S|
> [ 75.399784] sd 0:0:0:0: [sda] Synchronizing SCSI cache
> [ 75.439170] sd 0:0:0:0: [sda] Stopping disk
> [ 75.501461] ACPI: PM: Preparing to enter system sleep state S5
> [ 75.502766] reboot: Power down
>
>
>
> Logs(resume):
> [ 1.063248] PM: hibernation: resume from hibernation
> [ 1.072868] Freezing user space processes
> [ 1.073707] Freezing user space processes completed (elapsed 0.000
> seconds)
> [ 1.075192] OOM killer disabled.
> [ 1.075837] Freezing remaining freezable tasks
> [ 1.078010] Freezing remaining freezable tasks completed (elapsed
> 0.001 seconds)
> [ 1.087489] PM: Using 3 thread(s) for lz4 decompression
> [ 1.088570] PM: Loading and decompressing image data (17495 pages)...
> [ 1.125549] PM: Image loading progress: 0%
> [ 1.190380] PM: Image loading progress: 10%
> [ 1.204963] PM: Image loading progress: 20%
> [ 1.218988] PM: Image loading progress: 30%
> [ 1.233697] PM: Image loading progress: 40%
> [ 1.248658] PM: Image loading progress: 50%
> [ 1.262910] PM: Image loading progress: 60%
> [ 1.276966] PM: Image loading progress: 70%
> [ 1.290517] PM: Image loading progress: 80%
> [ 1.305427] PM: Image loading progress: 90%
> [ 1.320666] PM: Image loading progress: 100%
> [ 1.321866] PM: Image loading done
> [ 1.322599] PM: hibernation: Read 69980 kbytes in 0.23 seconds
> (304.26 MB/s)
> [ 1.324795] printk: Suspending console(s) (use no_console_suspend to
> debug)
> [ 74.943801] ata1.00: Entering standby power mode
>
>
> Thanks,
> Nikhil V

2024-01-22 12:14:23

by Nikhil V

[permalink] [raw]
Subject: Re: [PATCH RESEND v2 0/4] PM: hibernate: LZ4 compression support



On 12/12/2023 6:14 PM, Rafael J. Wysocki wrote:
> Hi,
>
> On Wed, Nov 29, 2023 at 11:20 AM Nikhil V <[email protected]> wrote:
>>
>>
>> On 11/15/2023 5:52 PM, Nikhil V wrote:
>>> This patch series covers the following:
>>> 1. Renaming lzo* to generic names, except for lzo_xxx() APIs. This is
>>> used in the next patch where we move to crypto based APIs for
>>> compression. There are no functional changes introduced by this
>>> approach.
>>>
>>>
>>> 2. Replace LZO library calls with crypto generic APIs
>>>
>>> Currently for hibernation, LZO is the only compression algorithm
>>> available and uses the existing LZO library calls. However, there
>>> is no flexibility to switch to other algorithms which provides better
>>> results. The main idea is that different compression algorithms have
>>> different characteristics and hibernation may benefit when it uses
>>> alternate algorithms.
>>>
>>> By moving to crypto based APIs, it lays a foundation to use other
>>> compression algorithms for hibernation.
>>>
>>>
>>> 3. LZ4 compression
>>>
>>> Extend the support for LZ4 compression to be used with hibernation.
>>> The main idea is that different compression algorithms have different
>>> characteristics and hibernation may benefit when it uses any of these
>>> algorithms: a default algorithm, having higher compression rate but is
>>> slower(compression/decompression) and a secondary algorithm, that is
>>> faster(compression/decompression) but has lower compression rate.
>>>
>>> LZ4 algorithm has better decompression speeds over LZO. This reduces
>>> the hibernation image restore time.
>>> As per test results:
>>> LZO LZ4
>>> Size before Compression(bytes) 682696704 682393600
>>> Size after Compression(bytes) 146502402 155993547
>>> Decompression Rate 335.02 MB/s 501.05 MB/s
>>> Restore time 4.4s 3.8s
>>>
>>> LZO is the default compression algorithm used for hibernation. Enable
>>> CONFIG_HIBERNATION_DEF_COMP_LZ4 to set the default compressor as LZ4.
>>>
>>> Compression Benchmarks: https://github.com/lz4/lz4
>>>
>>>
>>> 4. Support to select compression algorithm
>>>
>>> Currently the default compression algorithm is selected based on
>>> Kconfig. Introduce a kernel command line parameter "hib_compression" to
>>> override this behaviour.
>>>
>>> Users can set "hib_compression" command line parameter to specify
>>> the algorithm.
>>> Usage:
>>> LZO: hib_compression=lzo
>>> LZ4: hib_compression=lz4
>>> LZO is the default compression algorithm used with hibernation.
>>>
>>>
>>> Changes in v2:
>>> - Fixed build issues reported by kernel test robot for ARCH=sh, [1].
>>> [1] https://lore.kernel.org/oe-kbuild-all/[email protected]/
>>>
>>> Nikhil V (4):
>>> PM: hibernate: Rename lzo* to make it generic
>>> PM: hibernate: Move to crypto APIs for LZO compression
>>> PM: hibernate: Add support for LZ4 compression for hibernation
>>> PM: hibernate: Support to select compression algorithm
>>>
>>> .../admin-guide/kernel-parameters.txt | 6 +
>>> kernel/power/Kconfig | 26 ++-
>>> kernel/power/hibernate.c | 85 +++++++-
>>> kernel/power/power.h | 19 ++
>>> kernel/power/swap.c | 189 +++++++++++-------
>>> 5 files changed, 251 insertions(+), 74 deletions(-)
>>>
>>>
>>> base-commit: b85ea95d086471afb4ad062012a4d73cd328fa86
>>
>> Hi @Rafael/@Pavel/@Len,
>>
>> Could you please let me know if you have any concerns on this approach?
>
> Not really a concern, but that is a significant change that I would
> rather make early in the cycle, which means after the 6.8 merge
> window.
>
> No need to resend unless there is something to address in which case
> I'll let you know.
>
> Thanks!
>
>> FYI: We have tested this on QEMU and its working fine.
>>
>> Logs(suspend):
>> [ 75.242227] PM: Using 3 thread(s) for lz4 compression
>> [ 75.243043] PM: Compressing and saving image data (17495 pages)...
>> [ 75.243917] PM: Image saving progress: 0%
>> [ 75.261727] PM: Image saving progress: 10%
>> [ 75.277968] PM: Image saving progress: 20%
>> [ 75.290927] PM: Image saving progress: 30%
>> [ 75.305186] PM: Image saving progress: 40%
>> [ 75.318252] PM: Image saving progress: 50%
>> [ 75.330310] PM: Image saving progress: 60%
>> [ 75.345906] PM: Image saving progress: 70%
>> [ 75.359054] PM: Image saving progress: 80%
>> [ 75.372176] PM: Image saving progress: 90%
>> [ 75.388411] PM: Image saving progress: 100%
>> [ 75.389775] PM: Image saving done
>> [ 75.390397] PM: hibernation: Wrote 69980 kbytes in 0.14 seconds
>> (499.85 MB/s)
>> [ 75.391591] PM: Image size after compression: 28242 kbytes
>> [ 75.393089] PM: S|
>> [ 75.399784] sd 0:0:0:0: [sda] Synchronizing SCSI cache
>> [ 75.439170] sd 0:0:0:0: [sda] Stopping disk
>> [ 75.501461] ACPI: PM: Preparing to enter system sleep state S5
>> [ 75.502766] reboot: Power down
>>
>>
>>
>> Logs(resume):
>> [ 1.063248] PM: hibernation: resume from hibernation
>> [ 1.072868] Freezing user space processes
>> [ 1.073707] Freezing user space processes completed (elapsed 0.000
>> seconds)
>> [ 1.075192] OOM killer disabled.
>> [ 1.075837] Freezing remaining freezable tasks
>> [ 1.078010] Freezing remaining freezable tasks completed (elapsed
>> 0.001 seconds)
>> [ 1.087489] PM: Using 3 thread(s) for lz4 decompression
>> [ 1.088570] PM: Loading and decompressing image data (17495 pages)...
>> [ 1.125549] PM: Image loading progress: 0%
>> [ 1.190380] PM: Image loading progress: 10%
>> [ 1.204963] PM: Image loading progress: 20%
>> [ 1.218988] PM: Image loading progress: 30%
>> [ 1.233697] PM: Image loading progress: 40%
>> [ 1.248658] PM: Image loading progress: 50%
>> [ 1.262910] PM: Image loading progress: 60%
>> [ 1.276966] PM: Image loading progress: 70%
>> [ 1.290517] PM: Image loading progress: 80%
>> [ 1.305427] PM: Image loading progress: 90%
>> [ 1.320666] PM: Image loading progress: 100%
>> [ 1.321866] PM: Image loading done
>> [ 1.322599] PM: hibernation: Read 69980 kbytes in 0.23 seconds
>> (304.26 MB/s)
>> [ 1.324795] printk: Suspending console(s) (use no_console_suspend to
>> debug)
>> [ 74.943801] ata1.00: Entering standby power mode
>>
>>
>> Thanks,
>> Nikhil V


Hi @Rafael

We have picked this patch series on 6.8-rc1 and tested the functionality
on QEMU. Its working fine. However, while applying the patches we could
see minor conflicts. Could you please let me know if we need to push a
new version after resolving these conflicts?

Thanks,
Nikhil V

2024-01-22 12:52:50

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH RESEND v2 0/4] PM: hibernate: LZ4 compression support

On Mon, Jan 22, 2024 at 1:14 PM Nikhil V <[email protected]> wrote:
>
>
>
> On 12/12/2023 6:14 PM, Rafael J. Wysocki wrote:
> > Hi,
> >
> > On Wed, Nov 29, 2023 at 11:20 AM Nikhil V <[email protected]> wrote:
> >>
> >>
> >> On 11/15/2023 5:52 PM, Nikhil V wrote:
> >>> This patch series covers the following:
> >>> 1. Renaming lzo* to generic names, except for lzo_xxx() APIs. This is
> >>> used in the next patch where we move to crypto based APIs for
> >>> compression. There are no functional changes introduced by this
> >>> approach.
> >>>
> >>>
> >>> 2. Replace LZO library calls with crypto generic APIs
> >>>
> >>> Currently for hibernation, LZO is the only compression algorithm
> >>> available and uses the existing LZO library calls. However, there
> >>> is no flexibility to switch to other algorithms which provides better
> >>> results. The main idea is that different compression algorithms have
> >>> different characteristics and hibernation may benefit when it uses
> >>> alternate algorithms.
> >>>
> >>> By moving to crypto based APIs, it lays a foundation to use other
> >>> compression algorithms for hibernation.
> >>>
> >>>
> >>> 3. LZ4 compression
> >>>
> >>> Extend the support for LZ4 compression to be used with hibernation.
> >>> The main idea is that different compression algorithms have different
> >>> characteristics and hibernation may benefit when it uses any of these
> >>> algorithms: a default algorithm, having higher compression rate but is
> >>> slower(compression/decompression) and a secondary algorithm, that is
> >>> faster(compression/decompression) but has lower compression rate.
> >>>
> >>> LZ4 algorithm has better decompression speeds over LZO. This reduces
> >>> the hibernation image restore time.
> >>> As per test results:
> >>> LZO LZ4
> >>> Size before Compression(bytes) 682696704 682393600
> >>> Size after Compression(bytes) 146502402 155993547
> >>> Decompression Rate 335.02 MB/s 501.05 MB/s
> >>> Restore time 4.4s 3.8s
> >>>
> >>> LZO is the default compression algorithm used for hibernation. Enable
> >>> CONFIG_HIBERNATION_DEF_COMP_LZ4 to set the default compressor as LZ4.
> >>>
> >>> Compression Benchmarks: https://github.com/lz4/lz4
> >>>
> >>>
> >>> 4. Support to select compression algorithm
> >>>
> >>> Currently the default compression algorithm is selected based on
> >>> Kconfig. Introduce a kernel command line parameter "hib_compression" to
> >>> override this behaviour.
> >>>
> >>> Users can set "hib_compression" command line parameter to specify
> >>> the algorithm.
> >>> Usage:
> >>> LZO: hib_compression=lzo
> >>> LZ4: hib_compression=lz4
> >>> LZO is the default compression algorithm used with hibernation.
> >>>
> >>>
> >>> Changes in v2:
> >>> - Fixed build issues reported by kernel test robot for ARCH=sh, [1].
> >>> [1] https://lore.kernel.org/oe-kbuild-all/[email protected]/
> >>>
> >>> Nikhil V (4):
> >>> PM: hibernate: Rename lzo* to make it generic
> >>> PM: hibernate: Move to crypto APIs for LZO compression
> >>> PM: hibernate: Add support for LZ4 compression for hibernation
> >>> PM: hibernate: Support to select compression algorithm
> >>>
> >>> .../admin-guide/kernel-parameters.txt | 6 +
> >>> kernel/power/Kconfig | 26 ++-
> >>> kernel/power/hibernate.c | 85 +++++++-
> >>> kernel/power/power.h | 19 ++
> >>> kernel/power/swap.c | 189 +++++++++++-------
> >>> 5 files changed, 251 insertions(+), 74 deletions(-)
> >>>
> >>>
> >>> base-commit: b85ea95d086471afb4ad062012a4d73cd328fa86
> >>
> >> Hi @Rafael/@Pavel/@Len,
> >>
> >> Could you please let me know if you have any concerns on this approach?
> >
> > Not really a concern, but that is a significant change that I would
> > rather make early in the cycle, which means after the 6.8 merge
> > window.
> >
> > No need to resend unless there is something to address in which case
> > I'll let you know.
> >
> > Thanks!
> >
> >> FYI: We have tested this on QEMU and its working fine.
> >>
> >> Logs(suspend):
> >> [ 75.242227] PM: Using 3 thread(s) for lz4 compression
> >> [ 75.243043] PM: Compressing and saving image data (17495 pages)...
> >> [ 75.243917] PM: Image saving progress: 0%
> >> [ 75.261727] PM: Image saving progress: 10%
> >> [ 75.277968] PM: Image saving progress: 20%
> >> [ 75.290927] PM: Image saving progress: 30%
> >> [ 75.305186] PM: Image saving progress: 40%
> >> [ 75.318252] PM: Image saving progress: 50%
> >> [ 75.330310] PM: Image saving progress: 60%
> >> [ 75.345906] PM: Image saving progress: 70%
> >> [ 75.359054] PM: Image saving progress: 80%
> >> [ 75.372176] PM: Image saving progress: 90%
> >> [ 75.388411] PM: Image saving progress: 100%
> >> [ 75.389775] PM: Image saving done
> >> [ 75.390397] PM: hibernation: Wrote 69980 kbytes in 0.14 seconds
> >> (499.85 MB/s)
> >> [ 75.391591] PM: Image size after compression: 28242 kbytes
> >> [ 75.393089] PM: S|
> >> [ 75.399784] sd 0:0:0:0: [sda] Synchronizing SCSI cache
> >> [ 75.439170] sd 0:0:0:0: [sda] Stopping disk
> >> [ 75.501461] ACPI: PM: Preparing to enter system sleep state S5
> >> [ 75.502766] reboot: Power down
> >>
> >>
> >>
> >> Logs(resume):
> >> [ 1.063248] PM: hibernation: resume from hibernation
> >> [ 1.072868] Freezing user space processes
> >> [ 1.073707] Freezing user space processes completed (elapsed 0.000
> >> seconds)
> >> [ 1.075192] OOM killer disabled.
> >> [ 1.075837] Freezing remaining freezable tasks
> >> [ 1.078010] Freezing remaining freezable tasks completed (elapsed
> >> 0.001 seconds)
> >> [ 1.087489] PM: Using 3 thread(s) for lz4 decompression
> >> [ 1.088570] PM: Loading and decompressing image data (17495 pages)..
> >> [ 1.125549] PM: Image loading progress: 0%
> >> [ 1.190380] PM: Image loading progress: 10%
> >> [ 1.204963] PM: Image loading progress: 20%
> >> [ 1.218988] PM: Image loading progress: 30%
> >> [ 1.233697] PM: Image loading progress: 40%
> >> [ 1.248658] PM: Image loading progress: 50%
> >> [ 1.262910] PM: Image loading progress: 60%
> >> [ 1.276966] PM: Image loading progress: 70%
> >> [ 1.290517] PM: Image loading progress: 80%
> >> [ 1.305427] PM: Image loading progress: 90%
> >> [ 1.320666] PM: Image loading progress: 100%
> >> [ 1.321866] PM: Image loading done
> >> [ 1.322599] PM: hibernation: Read 69980 kbytes in 0.23 seconds
> >> (304.26 MB/s)
> >> [ 1.324795] printk: Suspending console(s) (use no_console_suspend to
> >> debug)
> >> [ 74.943801] ata1.00: Entering standby power mode
> >>
> >>
> >> Thanks,
> >> Nikhil V
>
>
> Hi @Rafael
>
> We have picked this patch series on 6.8-rc1 and tested the functionality
> on QEMU. Its working fine. However, while applying the patches we could
> see minor conflicts. Could you please let me know if we need to push a
> new version after resolving these conflicts?

It will help.

I can resolve the conflicts, but I may make mistakes in the process.

Thanks!

2024-01-22 13:18:58

by Nikhil V

[permalink] [raw]
Subject: Re: [PATCH RESEND v2 0/4] PM: hibernate: LZ4 compression support



On 1/22/2024 5:46 PM, Rafael J. Wysocki wrote:
> On Mon, Jan 22, 2024 at 1:14 PM Nikhil V <[email protected]> wrote:
>>
>>
>>
>> On 12/12/2023 6:14 PM, Rafael J. Wysocki wrote:
>>> Hi,
>>>
>>> On Wed, Nov 29, 2023 at 11:20 AM Nikhil V <[email protected]> wrote:
>>>>
>>>>
>>>> On 11/15/2023 5:52 PM, Nikhil V wrote:
>>>>> This patch series covers the following:
>>>>> 1. Renaming lzo* to generic names, except for lzo_xxx() APIs. This is
>>>>> used in the next patch where we move to crypto based APIs for
>>>>> compression. There are no functional changes introduced by this
>>>>> approach.
>>>>>
>>>>>
>>>>> 2. Replace LZO library calls with crypto generic APIs
>>>>>
>>>>> Currently for hibernation, LZO is the only compression algorithm
>>>>> available and uses the existing LZO library calls. However, there
>>>>> is no flexibility to switch to other algorithms which provides better
>>>>> results. The main idea is that different compression algorithms have
>>>>> different characteristics and hibernation may benefit when it uses
>>>>> alternate algorithms.
>>>>>
>>>>> By moving to crypto based APIs, it lays a foundation to use other
>>>>> compression algorithms for hibernation.
>>>>>
>>>>>
>>>>> 3. LZ4 compression
>>>>>
>>>>> Extend the support for LZ4 compression to be used with hibernation.
>>>>> The main idea is that different compression algorithms have different
>>>>> characteristics and hibernation may benefit when it uses any of these
>>>>> algorithms: a default algorithm, having higher compression rate but is
>>>>> slower(compression/decompression) and a secondary algorithm, that is
>>>>> faster(compression/decompression) but has lower compression rate.
>>>>>
>>>>> LZ4 algorithm has better decompression speeds over LZO. This reduces
>>>>> the hibernation image restore time.
>>>>> As per test results:
>>>>> LZO LZ4
>>>>> Size before Compression(bytes) 682696704 682393600
>>>>> Size after Compression(bytes) 146502402 155993547
>>>>> Decompression Rate 335.02 MB/s 501.05 MB/s
>>>>> Restore time 4.4s 3.8s
>>>>>
>>>>> LZO is the default compression algorithm used for hibernation. Enable
>>>>> CONFIG_HIBERNATION_DEF_COMP_LZ4 to set the default compressor as LZ4.
>>>>>
>>>>> Compression Benchmarks: https://github.com/lz4/lz4
>>>>>
>>>>>
>>>>> 4. Support to select compression algorithm
>>>>>
>>>>> Currently the default compression algorithm is selected based on
>>>>> Kconfig. Introduce a kernel command line parameter "hib_compression" to
>>>>> override this behaviour.
>>>>>
>>>>> Users can set "hib_compression" command line parameter to specify
>>>>> the algorithm.
>>>>> Usage:
>>>>> LZO: hib_compression=lzo
>>>>> LZ4: hib_compression=lz4
>>>>> LZO is the default compression algorithm used with hibernation.
>>>>>
>>>>>
>>>>> Changes in v2:
>>>>> - Fixed build issues reported by kernel test robot for ARCH=sh, [1].
>>>>> [1] https://lore.kernel.org/oe-kbuild-all/[email protected]/
>>>>>
>>>>> Nikhil V (4):
>>>>> PM: hibernate: Rename lzo* to make it generic
>>>>> PM: hibernate: Move to crypto APIs for LZO compression
>>>>> PM: hibernate: Add support for LZ4 compression for hibernation
>>>>> PM: hibernate: Support to select compression algorithm
>>>>>
>>>>> .../admin-guide/kernel-parameters.txt | 6 +
>>>>> kernel/power/Kconfig | 26 ++-
>>>>> kernel/power/hibernate.c | 85 +++++++-
>>>>> kernel/power/power.h | 19 ++
>>>>> kernel/power/swap.c | 189 +++++++++++-------
>>>>> 5 files changed, 251 insertions(+), 74 deletions(-)
>>>>>
>>>>>
>>>>> base-commit: b85ea95d086471afb4ad062012a4d73cd328fa86
>>>>
>>>> Hi @Rafael/@Pavel/@Len,
>>>>
>>>> Could you please let me know if you have any concerns on this approach?
>>>
>>> Not really a concern, but that is a significant change that I would
>>> rather make early in the cycle, which means after the 6.8 merge
>>> window.
>>>
>>> No need to resend unless there is something to address in which case
>>> I'll let you know.
>>>
>>> Thanks!
>>>
>>>> FYI: We have tested this on QEMU and its working fine.
>>>>
>>>> Logs(suspend):
>>>> [ 75.242227] PM: Using 3 thread(s) for lz4 compression
>>>> [ 75.243043] PM: Compressing and saving image data (17495 pages)...
>>>> [ 75.243917] PM: Image saving progress: 0%
>>>> [ 75.261727] PM: Image saving progress: 10%
>>>> [ 75.277968] PM: Image saving progress: 20%
>>>> [ 75.290927] PM: Image saving progress: 30%
>>>> [ 75.305186] PM: Image saving progress: 40%
>>>> [ 75.318252] PM: Image saving progress: 50%
>>>> [ 75.330310] PM: Image saving progress: 60%
>>>> [ 75.345906] PM: Image saving progress: 70%
>>>> [ 75.359054] PM: Image saving progress: 80%
>>>> [ 75.372176] PM: Image saving progress: 90%
>>>> [ 75.388411] PM: Image saving progress: 100%
>>>> [ 75.389775] PM: Image saving done
>>>> [ 75.390397] PM: hibernation: Wrote 69980 kbytes in 0.14 seconds
>>>> (499.85 MB/s)
>>>> [ 75.391591] PM: Image size after compression: 28242 kbytes
>>>> [ 75.393089] PM: S|
>>>> [ 75.399784] sd 0:0:0:0: [sda] Synchronizing SCSI cache
>>>> [ 75.439170] sd 0:0:0:0: [sda] Stopping disk
>>>> [ 75.501461] ACPI: PM: Preparing to enter system sleep state S5
>>>> [ 75.502766] reboot: Power down
>>>>
>>>>
>>>>
>>>> Logs(resume):
>>>> [ 1.063248] PM: hibernation: resume from hibernation
>>>> [ 1.072868] Freezing user space processes
>>>> [ 1.073707] Freezing user space processes completed (elapsed 0.000
>>>> seconds)
>>>> [ 1.075192] OOM killer disabled.
>>>> [ 1.075837] Freezing remaining freezable tasks
>>>> [ 1.078010] Freezing remaining freezable tasks completed (elapsed
>>>> 0.001 seconds)
>>>> [ 1.087489] PM: Using 3 thread(s) for lz4 decompression
>>>> [ 1.088570] PM: Loading and decompressing image data (17495 pages)...
>>>> [ 1.125549] PM: Image loading progress: 0%
>>>> [ 1.190380] PM: Image loading progress: 10%
>>>> [ 1.204963] PM: Image loading progress: 20%
>>>> [ 1.218988] PM: Image loading progress: 30%
>>>> [ 1.233697] PM: Image loading progress: 40%
>>>> [ 1.248658] PM: Image loading progress: 50%
>>>> [ 1.262910] PM: Image loading progress: 60%
>>>> [ 1.276966] PM: Image loading progress: 70%
>>>> [ 1.290517] PM: Image loading progress: 80%
>>>> [ 1.305427] PM: Image loading progress: 90%
>>>> [ 1.320666] PM: Image loading progress: 100%
>>>> [ 1.321866] PM: Image loading done
>>>> [ 1.322599] PM: hibernation: Read 69980 kbytes in 0.23 seconds
>>>> (304.26 MB/s)
>>>> [ 1.324795] printk: Suspending console(s) (use no_console_suspend to
>>>> debug)
>>>> [ 74.943801] ata1.00: Entering standby power mode
>>>>
>>>>
>>>> Thanks,
>>>> Nikhil V
>>
>>
>> Hi @Rafael
>>
>> We have picked this patch series on 6.8-rc1 and tested the functionality
>> on QEMU. Its working fine. However, while applying the patches we could
>> see minor conflicts. Could you please let me know if we need to push a
>> new version after resolving these conflicts?
>
> It will help.
>
> I can resolve the conflicts, but I may make mistakes in the process.
>
> Thanks!

Thanks for the response. Will push a new version after resolving the
conflicts.

Thanks,
Nikhil V