Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * JFFS2 -- Journalling Flash File System, Version 2.
0003  *
0004  * Copyright © 2001-2007 Red Hat, Inc.
0005  * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
0006  *
0007  * Created by David Woodhouse <dwmw2@infradead.org>
0008  *
0009  * For licensing information, see the file 'LICENCE' in this directory.
0010  *
0011  */
0012 
0013 #if !defined(__KERNEL__) && !defined(__ECOS)
0014 #error "The userspace support got too messy and was removed. Update your mkfs.jffs2"
0015 #endif
0016 
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018 
0019 #include <linux/kernel.h>
0020 #include <linux/zlib.h>
0021 #include <linux/zutil.h>
0022 #include "nodelist.h"
0023 #include "compr.h"
0024 
0025     /* Plan: call deflate() with avail_in == *sourcelen,
0026         avail_out = *dstlen - 12 and flush == Z_FINISH.
0027         If it doesn't manage to finish, call it again with
0028         avail_in == 0 and avail_out set to the remaining 12
0029         bytes for it to clean up.
0030        Q: Is 12 bytes sufficient?
0031     */
0032 #define STREAM_END_SPACE 12
0033 
0034 static DEFINE_MUTEX(deflate_mutex);
0035 static DEFINE_MUTEX(inflate_mutex);
0036 static z_stream inf_strm, def_strm;
0037 
0038 #ifdef __KERNEL__ /* Linux-only */
0039 #include <linux/vmalloc.h>
0040 #include <linux/init.h>
0041 #include <linux/mutex.h>
0042 
0043 static int __init alloc_workspaces(void)
0044 {
0045     def_strm.workspace = vmalloc(zlib_deflate_workspacesize(MAX_WBITS,
0046                             MAX_MEM_LEVEL));
0047     if (!def_strm.workspace)
0048         return -ENOMEM;
0049 
0050     jffs2_dbg(1, "Allocated %d bytes for deflate workspace\n",
0051           zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL));
0052     inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
0053     if (!inf_strm.workspace) {
0054         vfree(def_strm.workspace);
0055         return -ENOMEM;
0056     }
0057     jffs2_dbg(1, "Allocated %d bytes for inflate workspace\n",
0058           zlib_inflate_workspacesize());
0059     return 0;
0060 }
0061 
0062 static void free_workspaces(void)
0063 {
0064     vfree(def_strm.workspace);
0065     vfree(inf_strm.workspace);
0066 }
0067 #else
0068 #define alloc_workspaces() (0)
0069 #define free_workspaces() do { } while(0)
0070 #endif /* __KERNEL__ */
0071 
0072 static int jffs2_zlib_compress(unsigned char *data_in,
0073                    unsigned char *cpage_out,
0074                    uint32_t *sourcelen, uint32_t *dstlen)
0075 {
0076     int ret;
0077 
0078     if (*dstlen <= STREAM_END_SPACE)
0079         return -1;
0080 
0081     mutex_lock(&deflate_mutex);
0082 
0083     if (Z_OK != zlib_deflateInit(&def_strm, 3)) {
0084         pr_warn("deflateInit failed\n");
0085         mutex_unlock(&deflate_mutex);
0086         return -1;
0087     }
0088 
0089     def_strm.next_in = data_in;
0090     def_strm.total_in = 0;
0091 
0092     def_strm.next_out = cpage_out;
0093     def_strm.total_out = 0;
0094 
0095     while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) {
0096         def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE);
0097         def_strm.avail_in = min_t(unsigned long,
0098             (*sourcelen-def_strm.total_in), def_strm.avail_out);
0099         jffs2_dbg(1, "calling deflate with avail_in %ld, avail_out %ld\n",
0100               def_strm.avail_in, def_strm.avail_out);
0101         ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH);
0102         jffs2_dbg(1, "deflate returned with avail_in %ld, avail_out %ld, total_in %ld, total_out %ld\n",
0103               def_strm.avail_in, def_strm.avail_out,
0104               def_strm.total_in, def_strm.total_out);
0105         if (ret != Z_OK) {
0106             jffs2_dbg(1, "deflate in loop returned %d\n", ret);
0107             zlib_deflateEnd(&def_strm);
0108             mutex_unlock(&deflate_mutex);
0109             return -1;
0110         }
0111     }
0112     def_strm.avail_out += STREAM_END_SPACE;
0113     def_strm.avail_in = 0;
0114     ret = zlib_deflate(&def_strm, Z_FINISH);
0115     zlib_deflateEnd(&def_strm);
0116 
0117     if (ret != Z_STREAM_END) {
0118         jffs2_dbg(1, "final deflate returned %d\n", ret);
0119         ret = -1;
0120         goto out;
0121     }
0122 
0123     if (def_strm.total_out >= def_strm.total_in) {
0124         jffs2_dbg(1, "zlib compressed %ld bytes into %ld; failing\n",
0125               def_strm.total_in, def_strm.total_out);
0126         ret = -1;
0127         goto out;
0128     }
0129 
0130     jffs2_dbg(1, "zlib compressed %ld bytes into %ld\n",
0131           def_strm.total_in, def_strm.total_out);
0132 
0133     *dstlen = def_strm.total_out;
0134     *sourcelen = def_strm.total_in;
0135     ret = 0;
0136  out:
0137     mutex_unlock(&deflate_mutex);
0138     return ret;
0139 }
0140 
0141 static int jffs2_zlib_decompress(unsigned char *data_in,
0142                  unsigned char *cpage_out,
0143                  uint32_t srclen, uint32_t destlen)
0144 {
0145     int ret;
0146     int wbits = MAX_WBITS;
0147 
0148     mutex_lock(&inflate_mutex);
0149 
0150     inf_strm.next_in = data_in;
0151     inf_strm.avail_in = srclen;
0152     inf_strm.total_in = 0;
0153 
0154     inf_strm.next_out = cpage_out;
0155     inf_strm.avail_out = destlen;
0156     inf_strm.total_out = 0;
0157 
0158     /* If it's deflate, and it's got no preset dictionary, then
0159        we can tell zlib to skip the adler32 check. */
0160     if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
0161         ((data_in[0] & 0x0f) == Z_DEFLATED) &&
0162         !(((data_in[0]<<8) + data_in[1]) % 31)) {
0163 
0164         jffs2_dbg(2, "inflate skipping adler32\n");
0165         wbits = -((data_in[0] >> 4) + 8);
0166         inf_strm.next_in += 2;
0167         inf_strm.avail_in -= 2;
0168     } else {
0169         /* Let this remain D1 for now -- it should never happen */
0170         jffs2_dbg(1, "inflate not skipping adler32\n");
0171     }
0172 
0173 
0174     if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) {
0175         pr_warn("inflateInit failed\n");
0176         mutex_unlock(&inflate_mutex);
0177         return 1;
0178     }
0179 
0180     while((ret = zlib_inflate(&inf_strm, Z_FINISH)) == Z_OK)
0181         ;
0182     if (ret != Z_STREAM_END) {
0183         pr_notice("inflate returned %d\n", ret);
0184     }
0185     zlib_inflateEnd(&inf_strm);
0186     mutex_unlock(&inflate_mutex);
0187     return 0;
0188 }
0189 
0190 static struct jffs2_compressor jffs2_zlib_comp = {
0191     .priority = JFFS2_ZLIB_PRIORITY,
0192     .name = "zlib",
0193     .compr = JFFS2_COMPR_ZLIB,
0194     .compress = &jffs2_zlib_compress,
0195     .decompress = &jffs2_zlib_decompress,
0196 #ifdef JFFS2_ZLIB_DISABLED
0197     .disabled = 1,
0198 #else
0199     .disabled = 0,
0200 #endif
0201 };
0202 
0203 int __init jffs2_zlib_init(void)
0204 {
0205     int ret;
0206 
0207     ret = alloc_workspaces();
0208     if (ret)
0209         return ret;
0210 
0211     ret = jffs2_register_compressor(&jffs2_zlib_comp);
0212     if (ret)
0213         free_workspaces();
0214 
0215     return ret;
0216 }
0217 
0218 void jffs2_zlib_exit(void)
0219 {
0220     jffs2_unregister_compressor(&jffs2_zlib_comp);
0221     free_workspaces();
0222 }