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 
14 static DEFINE_MUTEX(compr_mutex);
15 static struct z_stream_s stream;
16 
logfs_compress(void * in,void * out,size_t inlen,size_t outlen)17 int 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;
46 error:
47 	mutex_unlock(&compr_mutex);
48 	return ret;
49 }
50 
logfs_uncompress(void * in,void * out,size_t inlen,size_t outlen)51 int 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;
77 error:
78 	mutex_unlock(&compr_mutex);
79 	return ret;
80 }
81 
logfs_compr_init(void)82 int __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 
logfs_compr_exit(void)92 void logfs_compr_exit(void)
93 {
94 	vfree(stream.workspace);
95 }
96