1/*
2 * fs/logfs/compr.c	- compression routines
3 *
4 * As should be obvious for Linux kernel code, license is GPLv2
5 *
6 * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
7 */
8#include "logfs.h"
9#include <linux/vmalloc.h>
10#include <linux/zlib.h>
11
12#define COMPR_LEVEL 3
13
14static DEFINE_MUTEX(compr_mutex);
15static struct z_stream_s stream;
16
17int logfs_compress(void *in, void *out, size_t inlen, size_t outlen)
18{
19	int err, ret;
20
21	ret = -EIO;
22	mutex_lock(&compr_mutex);
23	err = zlib_deflateInit(&stream, COMPR_LEVEL);
24	if (err != Z_OK)
25		goto error;
26
27	stream.next_in = in;
28	stream.avail_in = inlen;
29	stream.total_in = 0;
30	stream.next_out = out;
31	stream.avail_out = outlen;
32	stream.total_out = 0;
33
34	err = zlib_deflate(&stream, Z_FINISH);
35	if (err != Z_STREAM_END)
36		goto error;
37
38	err = zlib_deflateEnd(&stream);
39	if (err != Z_OK)
40		goto error;
41
42	if (stream.total_out >= stream.total_in)
43		goto error;
44
45	ret = stream.total_out;
46error:
47	mutex_unlock(&compr_mutex);
48	return ret;
49}
50
51int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen)
52{
53	int err, ret;
54
55	ret = -EIO;
56	mutex_lock(&compr_mutex);
57	err = zlib_inflateInit(&stream);
58	if (err != Z_OK)
59		goto error;
60
61	stream.next_in = in;
62	stream.avail_in = inlen;
63	stream.total_in = 0;
64	stream.next_out = out;
65	stream.avail_out = outlen;
66	stream.total_out = 0;
67
68	err = zlib_inflate(&stream, Z_FINISH);
69	if (err != Z_STREAM_END)
70		goto error;
71
72	err = zlib_inflateEnd(&stream);
73	if (err != Z_OK)
74		goto error;
75
76	ret = 0;
77error:
78	mutex_unlock(&compr_mutex);
79	return ret;
80}
81
82int __init logfs_compr_init(void)
83{
84	size_t size = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
85			zlib_inflate_workspacesize());
86	stream.workspace = vmalloc(size);
87	if (!stream.workspace)
88		return -ENOMEM;
89	return 0;
90}
91
92void logfs_compr_exit(void)
93{
94	vfree(stream.workspace);
95}
96