0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0026
0027
0028
0029
0030
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__
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
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
0159
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
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 }