mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays
@ 2025-10-21 11:37 Xueqin Luo
  2025-10-21 11:37 ` [PATCH v5 1/3] PM: hibernate: dynamically allocate crc->unc_len/unc for configurable threads Xueqin Luo
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Xueqin Luo @ 2025-10-21 11:37 UTC (permalink / raw)
  To: rafael, pavel, lenb, linux-pm, linux-kernel; +Cc: Xueqin Luo

Hi,

This is v5 of the series to make hibernate compression/decompression
threads configurable and improve scalability.

Following feedback from previous versions:

- Patch 2 (`PM: hibernate: make compression threads configurable`) has been updated
  to rename the GRUB/kernel command line parameter from `cmp_threads` to
  `hibernate_compression_threads`, making its purpose clearer and more
  self-explanatory.

- Patch 3 (`PM: hibernate: add sysfs interface for hibernate_compression_threads`)
  has been added to provide a runtime interface under
  `/sys/power/hibernate_compression_threads`. This allows users and
  system integrators to tune the number of compression/decompression
  threads dynamically without rebooting the system.

- Corresponding documentation updates have been added:
  - `Documentation/admin-guide/kernel-parameters.txt` now documents
    `hibernate_compression_threads=` GRUB parameter.
  - `Documentation/ABI/testing/sysfs-power` describes the new sysfs interface.

This series ensures that both boot-time and runtime configuration of
hibernate compression threads are supported, improving flexibility
and scalability on multi-core systems.

Xueqin Luo (3):
  PM: hibernate: dynamically allocate crc->unc_len/unc for configurable
    threads
  PM: hibernate: make compression threads configurable
  PM: hibernate: add sysfs interface for hibernate_compression_threads

 Documentation/ABI/testing/sysfs-power         |  16 +++
 .../admin-guide/kernel-parameters.txt         |  10 ++
 kernel/power/swap.c                           | 121 +++++++++++++++---
 3 files changed, 129 insertions(+), 18 deletions(-)

-- 
2.43.0


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

* [PATCH v5 1/3] PM: hibernate: dynamically allocate crc->unc_len/unc for configurable threads
  2025-10-21 11:37 [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays Xueqin Luo
@ 2025-10-21 11:37 ` Xueqin Luo
  2025-10-21 11:37 ` [PATCH v5 2/3] PM: hibernate: make compression threads configurable Xueqin Luo
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Xueqin Luo @ 2025-10-21 11:37 UTC (permalink / raw)
  To: rafael, pavel, lenb, linux-pm, linux-kernel; +Cc: Xueqin Luo

Convert crc->unc_len and crc->unc from fixed-size arrays to dynamically
allocated arrays, sized according to the actual number of threads selected
at runtime. This removes the fixed limit imposed by CMP_THREADS.

Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
---
 kernel/power/swap.c | 58 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 14 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 0beff7eeaaba..f8c13f5672ec 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -585,10 +585,48 @@ 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[CMP_THREADS];             /* uncompressed lengths */
-	unsigned char *unc[CMP_THREADS];          /* uncompressed data */
+	size_t **unc_len;			  /* uncompressed lengths */
+	unsigned char **unc;			  /* uncompressed data */
 };
 
+static struct crc_data *alloc_crc_data(int nr_threads)
+{
+	struct crc_data *crc;
+
+	crc = kzalloc(sizeof(*crc), GFP_KERNEL);
+	if (!crc)
+		return NULL;
+
+	crc->unc = kcalloc(nr_threads, sizeof(*crc->unc), GFP_KERNEL);
+	if (!crc->unc)
+		goto err_free_crc;
+
+	crc->unc_len = kcalloc(nr_threads, sizeof(*crc->unc_len), GFP_KERNEL);
+	if (!crc->unc_len)
+		goto err_free_unc;
+
+	return crc;
+
+err_free_unc:
+	kfree(crc->unc);
+err_free_crc:
+	kfree(crc);
+	return NULL;
+}
+
+static void free_crc_data(struct crc_data *crc)
+{
+	if (!crc)
+		return;
+
+	if (crc->thr)
+		kthread_stop(crc->thr);
+
+	kfree(crc->unc_len);
+	kfree(crc->unc);
+	kfree(crc);
+}
+
 /*
  * CRC32 update function that runs in its own thread.
  */
@@ -719,7 +757,7 @@ static int save_compressed_image(struct swap_map_handle *handle,
 		goto out_clean;
 	}
 
-	crc = kzalloc(sizeof(*crc), GFP_KERNEL);
+	crc = alloc_crc_data(nr_threads);
 	if (!crc) {
 		pr_err("Failed to allocate crc\n");
 		ret = -ENOMEM;
@@ -885,11 +923,7 @@ static int save_compressed_image(struct swap_map_handle *handle,
 
 out_clean:
 	hib_finish_batch(&hb);
-	if (crc) {
-		if (crc->thr)
-			kthread_stop(crc->thr);
-		kfree(crc);
-	}
+	free_crc_data(crc);
 	if (data) {
 		for (thr = 0; thr < nr_threads; thr++) {
 			if (data[thr].thr)
@@ -1239,7 +1273,7 @@ static int load_compressed_image(struct swap_map_handle *handle,
 		goto out_clean;
 	}
 
-	crc = kzalloc(sizeof(*crc), GFP_KERNEL);
+	crc = alloc_crc_data(nr_threads);
 	if (!crc) {
 		pr_err("Failed to allocate crc\n");
 		ret = -ENOMEM;
@@ -1506,11 +1540,7 @@ static int load_compressed_image(struct swap_map_handle *handle,
 	hib_finish_batch(&hb);
 	for (i = 0; i < ring_size; i++)
 		free_page((unsigned long)page[i]);
-	if (crc) {
-		if (crc->thr)
-			kthread_stop(crc->thr);
-		kfree(crc);
-	}
+	free_crc_data(crc);
 	if (data) {
 		for (thr = 0; thr < nr_threads; thr++) {
 			if (data[thr].thr)
-- 
2.43.0


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

* [PATCH v5 2/3] PM: hibernate: make compression threads configurable
  2025-10-21 11:37 [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays Xueqin Luo
  2025-10-21 11:37 ` [PATCH v5 1/3] PM: hibernate: dynamically allocate crc->unc_len/unc for configurable threads Xueqin Luo
@ 2025-10-21 11:37 ` Xueqin Luo
  2025-10-21 11:37 ` [PATCH v5 3/3] PM: hibernate: add sysfs interface for hibernate_compression_threads Xueqin Luo
  2025-10-30 19:09 ` [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays Rafael J. Wysocki
  3 siblings, 0 replies; 5+ messages in thread
From: Xueqin Luo @ 2025-10-21 11:37 UTC (permalink / raw)
  To: rafael, pavel, lenb, linux-pm, linux-kernel; +Cc: Xueqin Luo

The number of compression/decompression threads has a direct impact on
hibernate image generation and resume latency. Using more threads can
reduce overall resume time, but on systems with fewer CPU cores it may
also introduce contention and reduce efficiency.

Performance was evaluated on an 8-core ARM system, averaged over 10 runs:

    Threads  Hibernate(s)  Resume(s)
    --------------------------------
       3         12.14       18.86
       4         12.28       17.48
       5         11.09       16.77
       6         11.08       16.44

With 5–6 threads, resume latency improves by approximately 12% compared
to the default 3-thread configuration, with negligible impact on
hibernate time.

Introduce a new kernel parameter `hibernate_compression_threads=` that
allows users and integrators to tune the number of
compression/decompression threads at boot. This provides a way to
balance performance and CPU utilization across a wide range of hardware
without recompiling the kernel.

Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
---
 .../admin-guide/kernel-parameters.txt         | 10 ++++++++
 kernel/power/swap.c                           | 25 ++++++++++++++++---
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index db84a629f7b1..fb577fb2c893 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1889,6 +1889,16 @@
 			/sys/power/pm_test). Only available when CONFIG_PM_DEBUG
 			is set. Default value is 5.
 
+	hibernate_compression_threads=
+			[HIBERNATION]
+			Set the number of threads used for compressing or decompressing
+			hibernation images.
+
+			Format: <integer>
+			Default: 3
+			Minimum: 1
+			Example: hibernate_compression_threads=4
+
 	highmem=nn[KMG]	[KNL,BOOT,EARLY] 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/swap.c b/kernel/power/swap.c
index f8c13f5672ec..aa11576e92a9 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -519,8 +519,9 @@ static int swap_writer_finish(struct swap_map_handle *handle,
 				CMP_HEADER, PAGE_SIZE)
 #define CMP_SIZE	(CMP_PAGES * PAGE_SIZE)
 
-/* Maximum number of threads for compression/decompression. */
-#define CMP_THREADS	3
+/* Default number of threads for compression/decompression. */
+#define CMP_THREADS    3
+static unsigned int hibernate_compression_threads = CMP_THREADS;
 
 /* Minimum/maximum number of pages for read buffering. */
 #define CMP_MIN_RD_PAGES	1024
@@ -741,7 +742,7 @@ static int save_compressed_image(struct swap_map_handle *handle,
 	 * footprint.
 	 */
 	nr_threads = num_online_cpus() - 1;
-	nr_threads = clamp_val(nr_threads, 1, CMP_THREADS);
+	nr_threads = clamp_val(nr_threads, 1, hibernate_compression_threads);
 
 	page = (void *)__get_free_page(GFP_NOIO | __GFP_HIGH);
 	if (!page) {
@@ -1257,7 +1258,7 @@ static int load_compressed_image(struct swap_map_handle *handle,
 	 * footprint.
 	 */
 	nr_threads = num_online_cpus() - 1;
-	nr_threads = clamp_val(nr_threads, 1, CMP_THREADS);
+	nr_threads = clamp_val(nr_threads, 1, hibernate_compression_threads);
 
 	page = vmalloc_array(CMP_MAX_RD_PAGES, sizeof(*page));
 	if (!page) {
@@ -1697,3 +1698,19 @@ static int __init swsusp_header_init(void)
 }
 
 core_initcall(swsusp_header_init);
+
+static int __init hibernate_compression_threads_setup(char *str)
+{
+	int rc = kstrtouint(str, 0, &hibernate_compression_threads);
+
+	if (rc)
+		return rc;
+
+	if (hibernate_compression_threads < 1)
+		hibernate_compression_threads = CMP_THREADS;
+
+	return 1;
+
+}
+
+__setup("hibernate_compression_threads=", hibernate_compression_threads_setup);
-- 
2.43.0


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

* [PATCH v5 3/3] PM: hibernate: add sysfs interface for hibernate_compression_threads
  2025-10-21 11:37 [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays Xueqin Luo
  2025-10-21 11:37 ` [PATCH v5 1/3] PM: hibernate: dynamically allocate crc->unc_len/unc for configurable threads Xueqin Luo
  2025-10-21 11:37 ` [PATCH v5 2/3] PM: hibernate: make compression threads configurable Xueqin Luo
@ 2025-10-21 11:37 ` Xueqin Luo
  2025-10-30 19:09 ` [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays Rafael J. Wysocki
  3 siblings, 0 replies; 5+ messages in thread
From: Xueqin Luo @ 2025-10-21 11:37 UTC (permalink / raw)
  To: rafael, pavel, lenb, linux-pm, linux-kernel; +Cc: Xueqin Luo

Add a sysfs attribute `/sys/power/hibernate_compression_threads` to
allow runtime configuration of the number of threads used for
compressing and decompressing hibernation images.

The new sysfs interface enables dynamic adjustment at runtime:

    # cat /sys/power/hibernate_compression_threads
    3
    # echo 4 > /sys/power/hibernate_compression_threads

This change provides greater flexibility for debugging and performance
tuning of hibernation without requiring a reboot.

Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
---
 Documentation/ABI/testing/sysfs-power | 16 +++++++++++
 kernel/power/swap.c                   | 38 +++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index 4d8e1ad020f0..d38da077905a 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -454,3 +454,19 @@ Description:
 		disables it.  Reads from the file return the current value.
 		The default is "1" if the build-time "SUSPEND_SKIP_SYNC" config
 		flag is unset, or "0" otherwise.
+
+What:           /sys/power/hibernate_compression_threads
+Date:           October 2025
+Contact:        <luoxueqin@kylinos.cn>
+Description:
+                Controls the number of threads used for compression
+                and decompression of hibernation images.
+
+                The value can be adjusted at runtime to balance
+                performance and CPU utilization.
+
+                The change takes effect on the next hibernation or
+                resume operation.
+
+                Minimum value: 1
+                Default value: 3
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index aa11576e92a9..d173e276b494 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -1689,8 +1689,46 @@ int swsusp_unmark(void)
 }
 #endif
 
+static ssize_t hibernate_compression_threads_show(struct kobject *kobj,
+				struct kobj_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "%d\n", hibernate_compression_threads);
+}
+
+static ssize_t hibernate_compression_threads_store(struct kobject *kobj,
+				struct kobj_attribute *attr,
+				const char *buf, size_t n)
+{
+	unsigned long val;
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 1)
+		return -EINVAL;
+
+	hibernate_compression_threads = val;
+	return n;
+}
+power_attr(hibernate_compression_threads);
+
+static struct attribute *g[] = {
+	&hibernate_compression_threads_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group attr_group = {
+	.attrs = g,
+};
+
 static int __init swsusp_header_init(void)
 {
+	int error;
+
+	error = sysfs_create_group(power_kobj, &attr_group);
+	if (error)
+		return -ENOMEM;
+
 	swsusp_header = (struct swsusp_header*) __get_free_page(GFP_KERNEL);
 	if (!swsusp_header)
 		panic("Could not allocate memory for swsusp_header\n");
-- 
2.43.0


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

* Re: [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays
  2025-10-21 11:37 [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays Xueqin Luo
                   ` (2 preceding siblings ...)
  2025-10-21 11:37 ` [PATCH v5 3/3] PM: hibernate: add sysfs interface for hibernate_compression_threads Xueqin Luo
@ 2025-10-30 19:09 ` Rafael J. Wysocki
  3 siblings, 0 replies; 5+ messages in thread
From: Rafael J. Wysocki @ 2025-10-30 19:09 UTC (permalink / raw)
  To: Xueqin Luo; +Cc: rafael, pavel, lenb, linux-pm, linux-kernel

On Tue, Oct 21, 2025 at 1:37 PM Xueqin Luo <luoxueqin@kylinos.cn> wrote:
>
> Hi,
>
> This is v5 of the series to make hibernate compression/decompression
> threads configurable and improve scalability.
>
> Following feedback from previous versions:
>
> - Patch 2 (`PM: hibernate: make compression threads configurable`) has been updated
>   to rename the GRUB/kernel command line parameter from `cmp_threads` to
>   `hibernate_compression_threads`, making its purpose clearer and more
>   self-explanatory.
>
> - Patch 3 (`PM: hibernate: add sysfs interface for hibernate_compression_threads`)
>   has been added to provide a runtime interface under
>   `/sys/power/hibernate_compression_threads`. This allows users and
>   system integrators to tune the number of compression/decompression
>   threads dynamically without rebooting the system.
>
> - Corresponding documentation updates have been added:
>   - `Documentation/admin-guide/kernel-parameters.txt` now documents
>     `hibernate_compression_threads=` GRUB parameter.
>   - `Documentation/ABI/testing/sysfs-power` describes the new sysfs interface.
>
> This series ensures that both boot-time and runtime configuration of
> hibernate compression threads are supported, improving flexibility
> and scalability on multi-core systems.
>
> Xueqin Luo (3):
>   PM: hibernate: dynamically allocate crc->unc_len/unc for configurable
>     threads
>   PM: hibernate: make compression threads configurable
>   PM: hibernate: add sysfs interface for hibernate_compression_threads

All applied as 6.19 material, thanks!

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

end of thread, other threads:[~2025-10-30 19:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-21 11:37 [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays Xueqin Luo
2025-10-21 11:37 ` [PATCH v5 1/3] PM: hibernate: dynamically allocate crc->unc_len/unc for configurable threads Xueqin Luo
2025-10-21 11:37 ` [PATCH v5 2/3] PM: hibernate: make compression threads configurable Xueqin Luo
2025-10-21 11:37 ` [PATCH v5 3/3] PM: hibernate: add sysfs interface for hibernate_compression_threads Xueqin Luo
2025-10-30 19:09 ` [PATCH v5 0/3] PM: hibernate: make compression threads configurable and support dynamic crc arrays Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®