compr_zlib.c

Joakim Tjernlund
2002-03-11T09:33:31Z

Hi all

I noticed that zlib.c by default adds a small header and a adler32 checksum to the compressed
data. This is not needed since JFFS2 adds it's own CRC32. There is an 'undocumented' way to
avoid the header and adler32 checksum, specify a negative windowBits to deflateInit2()/inflateInit2().
Also it is possible to trim the memory usage by adjusting windowBits and memLevel accordinly. I have
left these at their default values since I don't know zlib very well. Perhaps someone else can comment?

Also I wonder about STREAM_END_SPACE, which is defined to 12. Is it useful to try and compress
data as small as 13 bytes with zlib? Maybe the simpler rtime should be used for small amounts of
data?

Below is a patch against the stable 2.4 branch, which is backwards compatible.

Jocke

PS.
There has been a few improvements to JFFS2 that I would like to see in the stable 2.4 branch, we
have been using these for about 2 weeks now and I think they are stable.

Index: fs/jffs2/compr_zlib.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/compr_zlib.c,v
retrieving revision 1.8
diff -u -r1.8 compr_zlib.c
--- fs/jffs2/compr_zlib.c 2001/09/20 15:28:31 1.8
+++ fs/jffs2/compr_zlib.c 2002/03/11 08:31:35
@@ -31,7 +31,7 @@
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
- * $Id: compr_zlib.c,v 1.8 2001/09/20 15:28:31 dwmw2 Exp $
+ * $Id: compr_zlib.c,v 1.8 2002/01/31 13:56:11 jocke Exp $
*
*/

@@ -92,9 +92,21 @@
strm.zalloc = (void *)0;
strm.zfree = (void *)0;
#endif
-
- if (Z_OK != deflateInit(&strm, 3)) {
- printk(KERN_WARNING "deflateInit failed\n");
+ /* The memory requirements for deflate are (in bytes):
+ 1 << (windowBits+2) + 1 << (memLevel+9)
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+ */
+ /* -MAX_WBITS impiles -> suppress zlib header and adler32 */
+ if (Z_OK != deflateInit2(&strm, 3, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY)) {
+ printk(KERN_WARNING "deflateInit2 failed\n");
return -1;
}
strm.next_in = data_in;
@@ -142,7 +154,7 @@
__u32 srclen, __u32 destlen)
{
z_stream strm;
- int ret;
+ int ret, wbits, i;

#ifdef __KERNEL__
strm.zalloc = zalloc;
@@ -151,23 +163,34 @@
strm.zalloc = (void *)0;
strm.zfree = (void *)0;
#endif
-
- if (Z_OK != inflateInit(&strm)) {
- printk(KERN_WARNING "inflateInit failed\n");
- return;
- }
- strm.next_in = data_in;
- strm.avail_in = srclen;
- strm.total_in = 0;
-
- strm.next_out = cpage_out;
- strm.avail_out = destlen;
- strm.total_out = 0;
+ /* -MAX_WBITS impiles -> suppress zlib header and adler32.
+ try first with -MAX_WBITS, if that fails, try MAX_WBITS to be
+ backwards compatible */
+ wbits = -MAX_WBITS;
+ for(i = 0; i < 2; i++){
+ if (Z_OK != inflateInit2(&strm, wbits)) {
+ printk(KERN_WARNING "inflateInit2 failed\n");
+ return;
+ }
+ strm.next_in = data_in;
+ strm.avail_in = srclen;
+ strm.total_in = 0;
+
+ strm.next_out = cpage_out;
+ strm.avail_out = destlen;
+ strm.total_out = 0;
+
+ while((ret = inflate(&strm, Z_FINISH)) == Z_OK)
+ ;
+ inflateEnd(&strm);
+ if (ret == Z_DATA_ERROR){
+ wbits = -wbits;
+ continue; /* try again with next wbits */
+ }

- while((ret = inflate(&strm, Z_FINISH)) == Z_OK)
- ;
- if (ret != Z_STREAM_END) {
- printk(KERN_NOTICE "inflate returned %d\n", ret);
+ if (ret != Z_STREAM_END) {
+ printk(KERN_NOTICE "inflate returned %d, wbits: %d\n", ret, wbits);
+ }
+ break; /* all went well */
}
- inflateEnd(&strm);
}