2009-11-21 03:13:39 +08:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
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: 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>
2011-03-23 07:35:12 +08:00
|
|
|
size_t size = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
|
2009-11-21 03:13:39 +08:00
|
|
|
zlib_inflate_workspacesize());
|
|
|
|
stream.workspace = vmalloc(size);
|
|
|
|
if (!stream.workspace)
|
|
|
|
return -ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void logfs_compr_exit(void)
|
|
|
|
{
|
|
|
|
vfree(stream.workspace);
|
|
|
|
}
|