xref: /openbmc/linux/fs/jffs2/compr.c (revision b6bec26c)
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   * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
7   *		    University of Szeged, Hungary
8   *
9   * Created by Arjan van de Ven <arjan@infradead.org>
10   *
11   * For licensing information, see the file 'LICENCE' in this directory.
12   *
13   */
14  
15  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16  
17  #include "compr.h"
18  
19  static DEFINE_SPINLOCK(jffs2_compressor_list_lock);
20  
21  /* Available compressors are on this list */
22  static LIST_HEAD(jffs2_compressor_list);
23  
24  /* Actual compression mode */
25  static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
26  
27  /* Statistics for blocks stored without compression */
28  static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
29  
30  
31  /*
32   * Return 1 to use this compression
33   */
34  static int jffs2_is_best_compression(struct jffs2_compressor *this,
35  		struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
36  {
37  	switch (jffs2_compression_mode) {
38  	case JFFS2_COMPR_MODE_SIZE:
39  		if (bestsize > size)
40  			return 1;
41  		return 0;
42  	case JFFS2_COMPR_MODE_FAVOURLZO:
43  		if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
44  			return 1;
45  		if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
46  			return 1;
47  		if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
48  			return 1;
49  		if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
50  			return 1;
51  
52  		return 0;
53  	}
54  	/* Shouldn't happen */
55  	return 0;
56  }
57  
58  /*
59   * jffs2_selected_compress:
60   * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
61   *	If 0, just take the first available compression mode.
62   * @data_in: Pointer to uncompressed data
63   * @cpage_out: Pointer to returned pointer to buffer for compressed data
64   * @datalen: On entry, holds the amount of data available for compression.
65   *	On exit, expected to hold the amount of data actually compressed.
66   * @cdatalen: On entry, holds the amount of space available for compressed
67   *	data. On exit, expected to hold the actual size of the compressed
68   *	data.
69   *
70   * Returns: the compression type used.  Zero is used to show that the data
71   * could not be compressed; probably because we couldn't find the requested
72   * compression mode.
73   */
74  static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
75  		unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
76  {
77  	struct jffs2_compressor *this;
78  	int err, ret = JFFS2_COMPR_NONE;
79  	uint32_t orig_slen, orig_dlen;
80  	char *output_buf;
81  
82  	output_buf = kmalloc(*cdatalen, GFP_KERNEL);
83  	if (!output_buf) {
84  		pr_warn("No memory for compressor allocation. Compression failed.\n");
85  		return ret;
86  	}
87  	orig_slen = *datalen;
88  	orig_dlen = *cdatalen;
89  	spin_lock(&jffs2_compressor_list_lock);
90  	list_for_each_entry(this, &jffs2_compressor_list, list) {
91  		/* Skip decompress-only and disabled modules */
92  		if (!this->compress || this->disabled)
93  			continue;
94  
95  		/* Skip if not the desired compression type */
96  		if (compr && (compr != this->compr))
97  			continue;
98  
99  		/*
100  		 * Either compression type was unspecified, or we found our
101  		 * compressor; either way, we're good to go.
102  		 */
103  		this->usecount++;
104  		spin_unlock(&jffs2_compressor_list_lock);
105  
106  		*datalen  = orig_slen;
107  		*cdatalen = orig_dlen;
108  		err = this->compress(data_in, output_buf, datalen, cdatalen);
109  
110  		spin_lock(&jffs2_compressor_list_lock);
111  		this->usecount--;
112  		if (!err) {
113  			/* Success */
114  			ret = this->compr;
115  			this->stat_compr_blocks++;
116  			this->stat_compr_orig_size += *datalen;
117  			this->stat_compr_new_size += *cdatalen;
118  			break;
119  		}
120  	}
121  	spin_unlock(&jffs2_compressor_list_lock);
122  	if (ret == JFFS2_COMPR_NONE)
123  		kfree(output_buf);
124  	else
125  		*cpage_out = output_buf;
126  
127  	return ret;
128  }
129  
130  /* jffs2_compress:
131   * @data_in: Pointer to uncompressed data
132   * @cpage_out: Pointer to returned pointer to buffer for compressed data
133   * @datalen: On entry, holds the amount of data available for compression.
134   *	On exit, expected to hold the amount of data actually compressed.
135   * @cdatalen: On entry, holds the amount of space available for compressed
136   *	data. On exit, expected to hold the actual size of the compressed
137   *	data.
138   *
139   * Returns: Lower byte to be stored with data indicating compression type used.
140   * Zero is used to show that the data could not be compressed - the
141   * compressed version was actually larger than the original.
142   * Upper byte will be used later. (soon)
143   *
144   * If the cdata buffer isn't large enough to hold all the uncompressed data,
145   * jffs2_compress should compress as much as will fit, and should set
146   * *datalen accordingly to show the amount of data which were compressed.
147   */
148  uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
149  			unsigned char *data_in, unsigned char **cpage_out,
150  			uint32_t *datalen, uint32_t *cdatalen)
151  {
152  	int ret = JFFS2_COMPR_NONE;
153  	int mode, compr_ret;
154  	struct jffs2_compressor *this, *best=NULL;
155  	unsigned char *output_buf = NULL, *tmp_buf;
156  	uint32_t orig_slen, orig_dlen;
157  	uint32_t best_slen=0, best_dlen=0;
158  
159  	if (c->mount_opts.override_compr)
160  		mode = c->mount_opts.compr;
161  	else
162  		mode = jffs2_compression_mode;
163  
164  	switch (mode) {
165  	case JFFS2_COMPR_MODE_NONE:
166  		break;
167  	case JFFS2_COMPR_MODE_PRIORITY:
168  		ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
169  				cdatalen);
170  		break;
171  	case JFFS2_COMPR_MODE_SIZE:
172  	case JFFS2_COMPR_MODE_FAVOURLZO:
173  		orig_slen = *datalen;
174  		orig_dlen = *cdatalen;
175  		spin_lock(&jffs2_compressor_list_lock);
176  		list_for_each_entry(this, &jffs2_compressor_list, list) {
177  			/* Skip decompress-only backwards-compatibility and disabled modules */
178  			if ((!this->compress)||(this->disabled))
179  				continue;
180  			/* Allocating memory for output buffer if necessary */
181  			if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
182  				spin_unlock(&jffs2_compressor_list_lock);
183  				kfree(this->compr_buf);
184  				spin_lock(&jffs2_compressor_list_lock);
185  				this->compr_buf_size=0;
186  				this->compr_buf=NULL;
187  			}
188  			if (!this->compr_buf) {
189  				spin_unlock(&jffs2_compressor_list_lock);
190  				tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
191  				spin_lock(&jffs2_compressor_list_lock);
192  				if (!tmp_buf) {
193  					pr_warn("No memory for compressor allocation. (%d bytes)\n",
194  						orig_slen);
195  					continue;
196  				}
197  				else {
198  					this->compr_buf = tmp_buf;
199  					this->compr_buf_size = orig_slen;
200  				}
201  			}
202  			this->usecount++;
203  			spin_unlock(&jffs2_compressor_list_lock);
204  			*datalen  = orig_slen;
205  			*cdatalen = orig_dlen;
206  			compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
207  			spin_lock(&jffs2_compressor_list_lock);
208  			this->usecount--;
209  			if (!compr_ret) {
210  				if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
211  						&& (*cdatalen < *datalen)) {
212  					best_dlen = *cdatalen;
213  					best_slen = *datalen;
214  					best = this;
215  				}
216  			}
217  		}
218  		if (best_dlen) {
219  			*cdatalen = best_dlen;
220  			*datalen  = best_slen;
221  			output_buf = best->compr_buf;
222  			best->compr_buf = NULL;
223  			best->compr_buf_size = 0;
224  			best->stat_compr_blocks++;
225  			best->stat_compr_orig_size += best_slen;
226  			best->stat_compr_new_size  += best_dlen;
227  			ret = best->compr;
228  			*cpage_out = output_buf;
229  		}
230  		spin_unlock(&jffs2_compressor_list_lock);
231  		break;
232  	case JFFS2_COMPR_MODE_FORCELZO:
233  		ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
234  				cpage_out, datalen, cdatalen);
235  		break;
236  	case JFFS2_COMPR_MODE_FORCEZLIB:
237  		ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
238  				cpage_out, datalen, cdatalen);
239  		break;
240  	default:
241  		pr_err("unknown compression mode\n");
242  	}
243  
244  	if (ret == JFFS2_COMPR_NONE) {
245  		*cpage_out = data_in;
246  		*datalen = *cdatalen;
247  		none_stat_compr_blocks++;
248  		none_stat_compr_size += *datalen;
249  	}
250  	return ret;
251  }
252  
253  int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
254  		     uint16_t comprtype, unsigned char *cdata_in,
255  		     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
256  {
257  	struct jffs2_compressor *this;
258  	int ret;
259  
260  	/* Older code had a bug where it would write non-zero 'usercompr'
261  	   fields. Deal with it. */
262  	if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB)
263  		comprtype &= 0xff;
264  
265  	switch (comprtype & 0xff) {
266  	case JFFS2_COMPR_NONE:
267  		/* This should be special-cased elsewhere, but we might as well deal with it */
268  		memcpy(data_out, cdata_in, datalen);
269  		none_stat_decompr_blocks++;
270  		break;
271  	case JFFS2_COMPR_ZERO:
272  		memset(data_out, 0, datalen);
273  		break;
274  	default:
275  		spin_lock(&jffs2_compressor_list_lock);
276  		list_for_each_entry(this, &jffs2_compressor_list, list) {
277  			if (comprtype == this->compr) {
278  				this->usecount++;
279  				spin_unlock(&jffs2_compressor_list_lock);
280  				ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
281  				spin_lock(&jffs2_compressor_list_lock);
282  				if (ret) {
283  					pr_warn("Decompressor \"%s\" returned %d\n",
284  						this->name, ret);
285  				}
286  				else {
287  					this->stat_decompr_blocks++;
288  				}
289  				this->usecount--;
290  				spin_unlock(&jffs2_compressor_list_lock);
291  				return ret;
292  			}
293  		}
294  		pr_warn("compression type 0x%02x not available\n", comprtype);
295  		spin_unlock(&jffs2_compressor_list_lock);
296  		return -EIO;
297  	}
298  	return 0;
299  }
300  
301  int jffs2_register_compressor(struct jffs2_compressor *comp)
302  {
303  	struct jffs2_compressor *this;
304  
305  	if (!comp->name) {
306  		pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n");
307  		return -1;
308  	}
309  	comp->compr_buf_size=0;
310  	comp->compr_buf=NULL;
311  	comp->usecount=0;
312  	comp->stat_compr_orig_size=0;
313  	comp->stat_compr_new_size=0;
314  	comp->stat_compr_blocks=0;
315  	comp->stat_decompr_blocks=0;
316  	jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name);
317  
318  	spin_lock(&jffs2_compressor_list_lock);
319  
320  	list_for_each_entry(this, &jffs2_compressor_list, list) {
321  		if (this->priority < comp->priority) {
322  			list_add(&comp->list, this->list.prev);
323  			goto out;
324  		}
325  	}
326  	list_add_tail(&comp->list, &jffs2_compressor_list);
327  out:
328  	D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
329  		printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
330  	})
331  
332  	spin_unlock(&jffs2_compressor_list_lock);
333  
334  	return 0;
335  }
336  
337  int jffs2_unregister_compressor(struct jffs2_compressor *comp)
338  {
339  	D2(struct jffs2_compressor *this);
340  
341  	jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name);
342  
343  	spin_lock(&jffs2_compressor_list_lock);
344  
345  	if (comp->usecount) {
346  		spin_unlock(&jffs2_compressor_list_lock);
347  		pr_warn("Compressor module is in use. Unregister failed.\n");
348  		return -1;
349  	}
350  	list_del(&comp->list);
351  
352  	D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
353  		printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
354  	})
355  	spin_unlock(&jffs2_compressor_list_lock);
356  	return 0;
357  }
358  
359  void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
360  {
361  	if (orig != comprbuf)
362  		kfree(comprbuf);
363  }
364  
365  int __init jffs2_compressors_init(void)
366  {
367  /* Registering compressors */
368  #ifdef CONFIG_JFFS2_ZLIB
369  	jffs2_zlib_init();
370  #endif
371  #ifdef CONFIG_JFFS2_RTIME
372  	jffs2_rtime_init();
373  #endif
374  #ifdef CONFIG_JFFS2_RUBIN
375  	jffs2_rubinmips_init();
376  	jffs2_dynrubin_init();
377  #endif
378  #ifdef CONFIG_JFFS2_LZO
379  	jffs2_lzo_init();
380  #endif
381  /* Setting default compression mode */
382  #ifdef CONFIG_JFFS2_CMODE_NONE
383  	jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
384  	jffs2_dbg(1, "default compression mode: none\n");
385  #else
386  #ifdef CONFIG_JFFS2_CMODE_SIZE
387  	jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
388  	jffs2_dbg(1, "default compression mode: size\n");
389  #else
390  #ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
391  	jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
392  	jffs2_dbg(1, "default compression mode: favourlzo\n");
393  #else
394  	jffs2_dbg(1, "default compression mode: priority\n");
395  #endif
396  #endif
397  #endif
398  	return 0;
399  }
400  
401  int jffs2_compressors_exit(void)
402  {
403  /* Unregistering compressors */
404  #ifdef CONFIG_JFFS2_LZO
405  	jffs2_lzo_exit();
406  #endif
407  #ifdef CONFIG_JFFS2_RUBIN
408  	jffs2_dynrubin_exit();
409  	jffs2_rubinmips_exit();
410  #endif
411  #ifdef CONFIG_JFFS2_RTIME
412  	jffs2_rtime_exit();
413  #endif
414  #ifdef CONFIG_JFFS2_ZLIB
415  	jffs2_zlib_exit();
416  #endif
417  	return 0;
418  }
419