Commit 3fec6e59 authored by Nikhil V's avatar Nikhil V Committed by Rafael J. Wysocki
Browse files

PM: hibernate: Support to select compression algorithm



Currently the default compression algorithm is selected based on
compile time options. Introduce a module parameter "hibernate.compressor"
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(LZ4) offers better decompression speeds over
a default algorithm(LZO), which in turn reduces hibernation image
restore time.

Users can override the default algorithm in two ways:

 1) Passing "hibernate.compressor" as kernel command line parameter.
    Usage:
    	LZO: hibernate.compressor=lzo
    	LZ4: hibernate.compressor=lz4

 2) Specifying the algorithm at runtime.
    Usage:
	LZO: echo lzo > /sys/module/hibernate/parameters/compressor
	LZ4: echo lz4 > /sys/module/hibernate/parameters/compressor

Currently LZO and LZ4 are the supported algorithms. LZO is the default
compression algorithm used with hibernation.

Signed-off-by: default avatarNikhil V <quic_nprakash@quicinc.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 9bb6c395
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -1748,6 +1748,17 @@
				(that will set all pages holding image data
				during restoration read-only).

	hibernate.compressor= 	[HIBERNATION] Compression algorithm to be
				used with hibernation.
				Format: { lzo | lz4 }
				Default: lzo

				lzo: Select LZO compression algorithm to
				compress/decompress hibernation image.

				lz4: Select LZ4 compression algorithm to
				compress/decompress hibernation image.

	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
+54 −3
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ dev_t swsusp_resume_device;
sector_t swsusp_resume_block;
__visible int in_suspend __nosavedata;

static const char *default_compressor = CONFIG_HIBERNATION_DEF_COMP;
static char hibernate_compressor[CRYPTO_MAX_ALG_NAME] = CONFIG_HIBERNATION_DEF_COMP;

/*
 * Compression/decompression algorithm to be used while saving/loading
@@ -748,7 +748,7 @@ 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));
		strscpy(hib_comp_algo, hibernate_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;
@@ -999,7 +999,7 @@ static int software_resume(void)
		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));
			strscpy(hib_comp_algo, COMPRESSION_ALGO_LZO, 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;
@@ -1422,6 +1422,57 @@ 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 hibernate_compressor_param_set(const char *compressor,
		const struct kernel_param *kp)
{
	unsigned int sleep_flags;
	int index, ret;

	sleep_flags = lock_system_sleep();

	index = sysfs_match_string(comp_alg_enabled, compressor);
	if (index >= 0) {
		ret = param_set_copystring(comp_alg_enabled[index], kp);
		if (!ret)
			strscpy(hib_comp_algo, comp_alg_enabled[index],
				sizeof(hib_comp_algo));
	} else {
		ret = index;
	}

	unlock_system_sleep(sleep_flags);

	if (ret)
		pr_debug("Cannot set specified compressor %s\n",
			 compressor);

	return ret;
}

static const struct kernel_param_ops hibernate_compressor_param_ops = {
	.set    = hibernate_compressor_param_set,
	.get    = param_get_string,
};

static struct kparam_string hibernate_compressor_param_string = {
	.maxlen = sizeof(hibernate_compressor),
	.string = hibernate_compressor,
};

module_param_cb(compressor, &hibernate_compressor_param_ops,
		&hibernate_compressor_param_string, 0644);
MODULE_PARM_DESC(compressor,
		 "Compression algorithm to be used with hibernation");

__setup("noresume", noresume_setup);
__setup("resume_offset=", resume_offset_setup);
__setup("resume=", resume_setup);