• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * JFFS2 -- Journalling Flash File System, Version 2.
3  *
4  * Copyright © 2001-2007 Red Hat, Inc.
5  * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
6  *
7  * Created by David Woodhouse <dwmw2@infradead.org>
8  *
9  * For licensing information, see the file 'LICENCE' in this directory.
10  *
11  */
12 
13 #include <linux/kernel.h>
14 #include <zlib.h>
15 #include <linux/zutil.h>
16 #include <linux/semaphore.h>
17 #include "nodelist.h"
18 #include "compr.h"
19 
20 	/* Plan: call deflate() with avail_in == *sourcelen,
21 		avail_out = *dstlen - 12 and flush == Z_FINISH.
22 		If it doesn't manage to finish,	call it again with
23 		avail_in == 0 and avail_out set to the remaining 12
24 		bytes for it to clean up.
25 	   Q: Is 12 bytes sufficient?
26 	*/
27 #define STREAM_END_SPACE 12
28 
29 static DEFINE_MUTEX(deflate_mutex);
30 static DEFINE_MUTEX(inflate_mutex);
31 static z_stream inf_strm, def_strm;
32 
33 #define alloc_workspaces() (0)
34 #define free_workspaces() do { } while(0)
35 
jffs2_zlib_compress(unsigned char * data_in,unsigned char * cpage_out,uint32_t * sourcelen,uint32_t * dstlen)36 static int jffs2_zlib_compress(unsigned char *data_in,
37 			       unsigned char *cpage_out,
38 			       uint32_t *sourcelen, uint32_t *dstlen)
39 {
40 	int ret;
41 
42 	if (*dstlen <= STREAM_END_SPACE)
43 		return -1;
44 
45 	mutex_lock(&deflate_mutex);
46 
47 	if (Z_OK != deflateInit(&def_strm, 3)) {
48 		pr_warn("deflateInit failed\n");
49 		mutex_unlock(&deflate_mutex);
50 		return -1;
51 	}
52 
53 	def_strm.next_in = data_in;
54 	def_strm.total_in = 0;
55 
56 	def_strm.next_out = cpage_out;
57 	def_strm.total_out = 0;
58 
59 	while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) {
60 		def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE);
61 		def_strm.avail_in = min_t(unsigned long,
62 			(*sourcelen-def_strm.total_in), def_strm.avail_out);
63 		jffs2_dbg(1, "calling deflate with avail_in %ld, avail_out %ld\n",
64 			  def_strm.avail_in, def_strm.avail_out);
65 		ret = deflate(&def_strm, Z_PARTIAL_FLUSH);
66 		jffs2_dbg(1, "deflate returned with avail_in %ld, avail_out %ld, total_in %ld, total_out %ld\n",
67 			  def_strm.avail_in, def_strm.avail_out,
68 			  def_strm.total_in, def_strm.total_out);
69 		if (ret != Z_OK) {
70 			jffs2_dbg(1, "deflate in loop returned %d\n", ret);
71 			deflateEnd(&def_strm);
72 			mutex_unlock(&deflate_mutex);
73 			return -1;
74 		}
75 	}
76 	def_strm.avail_out += STREAM_END_SPACE;
77 	def_strm.avail_in = 0;
78 	ret = deflate(&def_strm, Z_FINISH);
79 	deflateEnd(&def_strm);
80 
81 	if (ret != Z_STREAM_END) {
82 		jffs2_dbg(1, "final deflate returned %d\n", ret);
83 		ret = -1;
84 		goto out;
85 	}
86 
87 	if (def_strm.total_out >= def_strm.total_in) {
88 		jffs2_dbg(1, "zlib compressed %ld bytes into %ld; failing\n",
89 			  def_strm.total_in, def_strm.total_out);
90 		ret = -1;
91 		goto out;
92 	}
93 
94 	jffs2_dbg(1, "zlib compressed %ld bytes into %ld\n",
95 		  def_strm.total_in, def_strm.total_out);
96 
97 	*dstlen = def_strm.total_out;
98 	*sourcelen = def_strm.total_in;
99 	ret = 0;
100  out:
101 	mutex_unlock(&deflate_mutex);
102 	return ret;
103 }
104 
jffs2_zlib_decompress(unsigned char * data_in,unsigned char * cpage_out,uint32_t srclen,uint32_t destlen)105 static int jffs2_zlib_decompress(unsigned char *data_in,
106 				 unsigned char *cpage_out,
107 				 uint32_t srclen, uint32_t destlen)
108 {
109 	int ret;
110 	int wbits = MAX_WBITS;
111 
112 	mutex_lock(&inflate_mutex);
113 
114 	inf_strm.next_in = data_in;
115 	inf_strm.avail_in = srclen;
116 	inf_strm.total_in = 0;
117 
118 	inf_strm.next_out = cpage_out;
119 	inf_strm.avail_out = destlen;
120 	inf_strm.total_out = 0;
121 
122 	/* If it's deflate, and it's got no preset dictionary, then
123 	   we can tell zlib to skip the adler32 check. */
124 	if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
125 	    ((data_in[0] & 0x0f) == Z_DEFLATED) &&
126 	    !(((data_in[0]<<8) + data_in[1]) % 31)) {
127 
128 		jffs2_dbg(2, "inflate skipping adler32\n");
129 		wbits = -((data_in[0] >> 4) + 8);
130 		inf_strm.next_in += 2;
131 		inf_strm.avail_in -= 2;
132 	} else {
133 		/* Let this remain D1 for now -- it should never happen */
134 		jffs2_dbg(1, "inflate not skipping adler32\n");
135 	}
136 
137 
138 	if (Z_OK != inflateInit2(&inf_strm, wbits)) {
139 		pr_warn("inflateInit failed\n");
140 		mutex_unlock(&inflate_mutex);
141 		return 1;
142 	}
143 
144 	while((ret = inflate(&inf_strm, Z_FINISH)) == Z_OK)
145 		;
146 	if (ret != Z_STREAM_END) {
147 		pr_notice("inflate returned %d\n", ret);
148 	}
149 	inflateEnd(&inf_strm);
150 	mutex_unlock(&inflate_mutex);
151 	return 0;
152 }
153 
154 static struct jffs2_compressor jffs2_zlib_comp = {
155     .priority = JFFS2_ZLIB_PRIORITY,
156     .name = "zlib",
157     .compr = JFFS2_COMPR_ZLIB,
158     .compress = &jffs2_zlib_compress,
159     .decompress = &jffs2_zlib_decompress,
160 #ifdef JFFS2_ZLIB_DISABLED
161     .disabled = 1,
162 #else
163     .disabled = 0,
164 #endif
165 };
166 
jffs2_zlib_init(void)167 int __init jffs2_zlib_init(void)
168 {
169     int ret;
170 
171     ret = alloc_workspaces();
172     if (ret)
173 	    return ret;
174 
175     pthread_mutex_init(&deflate_mutex, NULL);
176     pthread_mutex_init(&inflate_mutex, NULL);
177     ret = jffs2_register_compressor(&jffs2_zlib_comp);
178     if (ret)
179 	    free_workspaces();
180 
181     return ret;
182 }
183 
jffs2_zlib_exit(void)184 void jffs2_zlib_exit(void)
185 {
186     pthread_mutex_destroy(&deflate_mutex);
187     pthread_mutex_destroy(&inflate_mutex);
188     jffs2_unregister_compressor(&jffs2_zlib_comp);
189     free_workspaces();
190 }
191