Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 565d76cb authored by Jim Keniston's avatar Jim Keniston Committed by Linus Torvalds
Browse files

zlib: slim down zlib_deflate() workspace when possible



Instead of always creating a huge (268K) deflate_workspace with the
maximum compression parameters (windowBits=15, memLevel=8), allow the
caller to obtain a smaller workspace by specifying smaller parameter
values.

For example, when capturing oops and panic reports to a medium with
limited capacity, such as NVRAM, compression may be the only way to
capture the whole report.  In this case, a small workspace (24K works
fine) is a win, whether you allocate the workspace when you need it (i.e.,
during an oops or panic) or at boot time.

I've verified that this patch works with all accepted values of windowBits
(positive and negative), memLevel, and compression level.

Signed-off-by: default avatarJim Keniston <jkenisto@us.ibm.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: David Miller <davem@davemloft.net>
Cc: Chris Mason <chris.mason@oracle.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b12d1259
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -48,7 +48,8 @@ static int deflate_comp_init(struct deflate_ctx *ctx)
	int ret = 0;
	int ret = 0;
	struct z_stream_s *stream = &ctx->comp_stream;
	struct z_stream_s *stream = &ctx->comp_stream;


	stream->workspace = vzalloc(zlib_deflate_workspacesize());
	stream->workspace = vzalloc(zlib_deflate_workspacesize(
				-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL));
	if (!stream->workspace) {
	if (!stream->workspace) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto out;
		goto out;
+11 −7
Original line number Original line Diff line number Diff line
@@ -85,6 +85,7 @@ static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
	struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
	struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
	struct z_stream_s *stream = &ctx->comp_stream;
	struct z_stream_s *stream = &ctx->comp_stream;
	struct nlattr *tb[ZLIB_COMP_MAX + 1];
	struct nlattr *tb[ZLIB_COMP_MAX + 1];
	int window_bits, mem_level;
	size_t workspacesize;
	size_t workspacesize;
	int ret;
	int ret;


@@ -94,7 +95,14 @@ static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,


	zlib_comp_exit(ctx);
	zlib_comp_exit(ctx);


	workspacesize = zlib_deflate_workspacesize();
	window_bits = tb[ZLIB_COMP_WINDOWBITS]
					? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
					: MAX_WBITS;
	mem_level = tb[ZLIB_COMP_MEMLEVEL]
					? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
					: DEF_MEM_LEVEL;

	workspacesize = zlib_deflate_workspacesize(window_bits, mem_level);
	stream->workspace = vzalloc(workspacesize);
	stream->workspace = vzalloc(workspacesize);
	if (!stream->workspace)
	if (!stream->workspace)
		return -ENOMEM;
		return -ENOMEM;
@@ -106,12 +114,8 @@ static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
				tb[ZLIB_COMP_METHOD]
				tb[ZLIB_COMP_METHOD]
					? nla_get_u32(tb[ZLIB_COMP_METHOD])
					? nla_get_u32(tb[ZLIB_COMP_METHOD])
					: Z_DEFLATED,
					: Z_DEFLATED,
				tb[ZLIB_COMP_WINDOWBITS]
				window_bits,
					? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
				mem_level,
					: MAX_WBITS,
				tb[ZLIB_COMP_MEMLEVEL]
					? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
					: DEF_MEM_LEVEL,
				tb[ZLIB_COMP_STRATEGY]
				tb[ZLIB_COMP_STRATEGY]
					? nla_get_u32(tb[ZLIB_COMP_STRATEGY])
					? nla_get_u32(tb[ZLIB_COMP_STRATEGY])
					: Z_DEFAULT_STRATEGY);
					: Z_DEFAULT_STRATEGY);
+1 −1
Original line number Original line Diff line number Diff line
@@ -129,7 +129,7 @@ static void *z_comp_alloc(unsigned char *options, int opt_len)


	state->strm.next_in   = NULL;
	state->strm.next_in   = NULL;
	state->w_size         = w_size;
	state->w_size         = w_size;
	state->strm.workspace = vmalloc(zlib_deflate_workspacesize());
	state->strm.workspace = vmalloc(zlib_deflate_workspacesize(-w_size, 8));
	if (state->strm.workspace == NULL)
	if (state->strm.workspace == NULL)
		goto out_free;
		goto out_free;


+2 −1
Original line number Original line Diff line number Diff line
@@ -57,7 +57,8 @@ static struct list_head *zlib_alloc_workspace(void)
	if (!workspace)
	if (!workspace)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);


	workspace->def_strm.workspace = vmalloc(zlib_deflate_workspacesize());
	workspace->def_strm.workspace = vmalloc(zlib_deflate_workspacesize(
						MAX_WBITS, MAX_MEM_LEVEL));
	workspace->inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
	workspace->inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
	workspace->buf = kmalloc(PAGE_CACHE_SIZE, GFP_NOFS);
	workspace->buf = kmalloc(PAGE_CACHE_SIZE, GFP_NOFS);
	if (!workspace->def_strm.workspace ||
	if (!workspace->def_strm.workspace ||
+4 −3
Original line number Original line Diff line number Diff line
@@ -40,12 +40,13 @@ static z_stream inf_strm, def_strm;


static int __init alloc_workspaces(void)
static int __init alloc_workspaces(void)
{
{
	def_strm.workspace = vmalloc(zlib_deflate_workspacesize());
	def_strm.workspace = vmalloc(zlib_deflate_workspacesize(MAX_WBITS,
							MAX_MEM_LEVEL));
	if (!def_strm.workspace) {
	if (!def_strm.workspace) {
		printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize());
		printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL));
		return -ENOMEM;
		return -ENOMEM;
	}
	}
	D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize()));
	D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL)));
	inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
	inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
	if (!inf_strm.workspace) {
	if (!inf_strm.workspace) {
		printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize());
		printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize());
Loading