Mercurial > ecos
diff packages/fs/jffs2/current/src/compr_zlib.c @ 570:a7947d436e85
Update to latest public JFFS2 sources
| author | gthomas |
|---|---|
| date | Wed, 05 Feb 2003 00:00:40 +0000 |
| parents | e0c0827131d1 |
| children | 18f99a0f0059 |
line wrap: on
line diff
--- a/packages/fs/jffs2/current/src/compr_zlib.c +++ b/packages/fs/jffs2/current/src/compr_zlib.c @@ -7,62 +7,23 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr_zlib.c,v 1.12 2002/01/25 01:49:26 dwmw2 Exp $ + * $Id: compr_zlib.c,v 1.22 2003/01/12 13:21:28 dwmw2 Exp $ * */ -/* Be careful - there are three environments are supported by this file. - * - Linux kernel. - * - eCos kernel. - * - Userspace (mkfs.jffs2). - */ +#if !defined(__KERNEL__) && !defined(__ECOS) +#error "The userspace support got too messy and was removed. Update your mkfs.jffs2" +#endif -#ifdef __ECOS - /* Compiling in eCos (or RedBoot) */ -#include <cyg/compress/zlib.h> -#include "jffs2port.h" -#include "nodelist.h" - -#elif defined(__KERNEL__) - /* Compiling in Linux kernel */ #include <linux/config.h> #include <linux/kernel.h> #include <linux/mtd/compatmac.h> /* for min() */ #include <linux/slab.h> -#include <linux/jffs2.h> +#include <linux/zlib.h> +#include <linux/zutil.h> +#include <asm/semaphore.h> #include "nodelist.h" -static void *zalloc(void *opaque, unsigned nr, unsigned size) -{ - /* How much does it request? Should we use vmalloc? Or be dynamic? */ - return kmalloc(nr * size, GFP_KERNEL); -} - -static void zfree(void *opaque, void *addr) -{ - kfree(addr); -} -#ifdef CONFIG_ZLIB /* 2.5 kernels will have a shared zlib, at last. */ -#include <linux/zlib.h> -#else -#include "zlib.h" -#endif - -#else - /* Compiling in Linux(ish) userspace */ -#define min(x,y) ((x)<(y)?(x):(y)) -#ifndef D1 -#define D1(x) -#endif -#define KERN_DEBUG -#define KERN_NOTICE -#define KERN_WARNING -#define printk printf -#include <stdint.h> -#include <stdio.h> -#include <zlib.h> -#endif - /* Plan: call deflate() with avail_in == *sourcelen, avail_out = *dstlen - 12 and flush == Z_FINISH. If it doesn't manage to finish, call it again with @@ -72,98 +33,145 @@ static void zfree(void *opaque, void *ad */ #define STREAM_END_SPACE 12 +static DECLARE_MUTEX(deflate_sem); +static DECLARE_MUTEX(inflate_sem); +static z_stream inf_strm, def_strm; + +#ifdef __KERNEL__ /* Linux-only */ +int __init jffs2_zlib_init(void) +{ + def_strm.workspace = vmalloc(zlib_deflate_workspacesize()); + if (!def_strm.workspace) { + printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize()); + return -ENOMEM; + } + D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize())); + inf_strm.workspace = vmalloc(zlib_inflate_workspacesize()); + if (!inf_strm.workspace) { + printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize()); + vfree(def_strm.workspace); + return -ENOMEM; + } + D1(printk(KERN_DEBUG "Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize())); + return 0; +} + +void jffs2_zlib_exit(void) +{ + vfree(def_strm.workspace); + vfree(inf_strm.workspace); +} +#endif /* __KERNEL__ */ + int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen) { - z_stream strm; int ret; if (*dstlen <= STREAM_END_SPACE) return -1; -#ifdef __KERNEL__ /* Linux needs own alloc/free funcs */ - strm.zalloc = zalloc; - strm.zfree = zfree; -#else /* eCos and userspace don't */ - strm.zalloc = (void *)0; - strm.zfree = (void *)0; -#endif + down(&deflate_sem); - if (Z_OK != deflateInit(&strm, 3)) { + if (Z_OK != zlib_deflateInit(&def_strm, 3)) { printk(KERN_WARNING "deflateInit failed\n"); + up(&deflate_sem); return -1; } - strm.next_in = data_in; - strm.total_in = 0; + + def_strm.next_in = data_in; + def_strm.total_in = 0; - strm.next_out = cpage_out; - strm.total_out = 0; + def_strm.next_out = cpage_out; + def_strm.total_out = 0; - while (strm.total_out < *dstlen - STREAM_END_SPACE && strm.total_in < *sourcelen) { - strm.avail_out = *dstlen - (strm.total_out + STREAM_END_SPACE); - strm.avail_in = min((unsigned)(*sourcelen-strm.total_in), strm.avail_out); + while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) { + def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE); + def_strm.avail_in = min((unsigned)(*sourcelen-def_strm.total_in), def_strm.avail_out); D1(printk(KERN_DEBUG "calling deflate with avail_in %d, avail_out %d\n", - strm.avail_in, strm.avail_out)); - ret = deflate(&strm, Z_PARTIAL_FLUSH); + def_strm.avail_in, def_strm.avail_out)); + ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", - strm.avail_in, strm.avail_out, strm.total_in, strm.total_out)); + def_strm.avail_in, def_strm.avail_out, def_strm.total_in, def_strm.total_out)); if (ret != Z_OK) { D1(printk(KERN_DEBUG "deflate in loop returned %d\n", ret)); - deflateEnd(&strm); + zlib_deflateEnd(&def_strm); + up(&deflate_sem); return -1; } } - strm.avail_out += STREAM_END_SPACE; - strm.avail_in = 0; - ret = deflate(&strm, Z_FINISH); + def_strm.avail_out += STREAM_END_SPACE; + def_strm.avail_in = 0; + ret = zlib_deflate(&def_strm, Z_FINISH); + zlib_deflateEnd(&def_strm); + if (ret != Z_STREAM_END) { D1(printk(KERN_DEBUG "final deflate returned %d\n", ret)); - deflateEnd(&strm); - return -1; + ret = -1; + goto out; } - deflateEnd(&strm); - - D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld\n", strm.total_in, strm.total_out)); - if (strm.total_out >= strm.total_in) - return -1; - + if (def_strm.total_out >= def_strm.total_in) { + D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld; failing\n", + def_strm.total_in, def_strm.total_out)); + ret = -1; + goto out; + } - *dstlen = strm.total_out; - *sourcelen = strm.total_in; - return 0; + D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld\n", + def_strm.total_in, def_strm.total_out)); + + *dstlen = def_strm.total_out; + *sourcelen = def_strm.total_in; + ret = 0; + out: + up(&deflate_sem); + return ret; } void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen) { - z_stream strm; int ret; + int wbits = MAX_WBITS; + + down(&inflate_sem); + + inf_strm.next_in = data_in; + inf_strm.avail_in = srclen; + inf_strm.total_in = 0; + + inf_strm.next_out = cpage_out; + inf_strm.avail_out = destlen; + inf_strm.total_out = 0; -#ifdef __KERNEL__ - strm.zalloc = zalloc; - strm.zfree = zfree; -#else - strm.zalloc = (void *)0; - strm.zfree = (void *)0; -#endif + /* If it's deflate, and it's got no preset dictionary, then + we can tell zlib to skip the adler32 check. */ + if (srclen > 2 && !(data_in[1] & PRESET_DICT) && + ((data_in[0] & 0x0f) == Z_DEFLATED) && + !(((data_in[0]<<8) + data_in[1]) % 31)) { - if (Z_OK != inflateInit(&strm)) { + D2(printk(KERN_DEBUG "inflate skipping adler32\n")); + wbits = -((data_in[0] >> 4) + 8); + inf_strm.next_in += 2; + inf_strm.avail_in -= 2; + } else { + /* Let this remain D1 for now -- it should never happen */ + D1(printk(KERN_DEBUG "inflate not skipping adler32\n")); + } + + + if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) { printk(KERN_WARNING "inflateInit failed\n"); + up(&inflate_sem); 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) + while((ret = zlib_inflate(&inf_strm, Z_FINISH)) == Z_OK) ; if (ret != Z_STREAM_END) { printk(KERN_NOTICE "inflate returned %d\n", ret); } - inflateEnd(&strm); + zlib_inflateEnd(&inf_strm); + up(&inflate_sem); }
