forked from Minki/linux
565d76cb7d
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: Jim 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
96 lines
1.8 KiB
C
96 lines
1.8 KiB
C
/*
|
|
* fs/logfs/compr.c - compression routines
|
|
*
|
|
* As should be obvious for Linux kernel code, license is GPLv2
|
|
*
|
|
* Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
|
|
*/
|
|
#include "logfs.h"
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/zlib.h>
|
|
|
|
#define COMPR_LEVEL 3
|
|
|
|
static DEFINE_MUTEX(compr_mutex);
|
|
static struct z_stream_s stream;
|
|
|
|
int logfs_compress(void *in, void *out, size_t inlen, size_t outlen)
|
|
{
|
|
int err, ret;
|
|
|
|
ret = -EIO;
|
|
mutex_lock(&compr_mutex);
|
|
err = zlib_deflateInit(&stream, COMPR_LEVEL);
|
|
if (err != Z_OK)
|
|
goto error;
|
|
|
|
stream.next_in = in;
|
|
stream.avail_in = inlen;
|
|
stream.total_in = 0;
|
|
stream.next_out = out;
|
|
stream.avail_out = outlen;
|
|
stream.total_out = 0;
|
|
|
|
err = zlib_deflate(&stream, Z_FINISH);
|
|
if (err != Z_STREAM_END)
|
|
goto error;
|
|
|
|
err = zlib_deflateEnd(&stream);
|
|
if (err != Z_OK)
|
|
goto error;
|
|
|
|
if (stream.total_out >= stream.total_in)
|
|
goto error;
|
|
|
|
ret = stream.total_out;
|
|
error:
|
|
mutex_unlock(&compr_mutex);
|
|
return ret;
|
|
}
|
|
|
|
int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen)
|
|
{
|
|
int err, ret;
|
|
|
|
ret = -EIO;
|
|
mutex_lock(&compr_mutex);
|
|
err = zlib_inflateInit(&stream);
|
|
if (err != Z_OK)
|
|
goto error;
|
|
|
|
stream.next_in = in;
|
|
stream.avail_in = inlen;
|
|
stream.total_in = 0;
|
|
stream.next_out = out;
|
|
stream.avail_out = outlen;
|
|
stream.total_out = 0;
|
|
|
|
err = zlib_inflate(&stream, Z_FINISH);
|
|
if (err != Z_STREAM_END)
|
|
goto error;
|
|
|
|
err = zlib_inflateEnd(&stream);
|
|
if (err != Z_OK)
|
|
goto error;
|
|
|
|
ret = 0;
|
|
error:
|
|
mutex_unlock(&compr_mutex);
|
|
return ret;
|
|
}
|
|
|
|
int __init logfs_compr_init(void)
|
|
{
|
|
size_t size = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
|
|
zlib_inflate_workspacesize());
|
|
stream.workspace = vmalloc(size);
|
|
if (!stream.workspace)
|
|
return -ENOMEM;
|
|
return 0;
|
|
}
|
|
|
|
void logfs_compr_exit(void)
|
|
{
|
|
vfree(stream.workspace);
|
|
}
|