162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc.
562306a36Sopenharmony_ci * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
662306a36Sopenharmony_ci * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
762306a36Sopenharmony_ci *		    University of Szeged, Hungary
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Created by Arjan van de Ven <arjan@infradead.org>
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "compr.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic DEFINE_SPINLOCK(jffs2_compressor_list_lock);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/* Available compressors are on this list */
2262306a36Sopenharmony_cistatic LIST_HEAD(jffs2_compressor_list);
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* Actual compression mode */
2562306a36Sopenharmony_cistatic int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* Statistics for blocks stored without compression */
2862306a36Sopenharmony_cistatic uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/*
3262306a36Sopenharmony_ci * Return 1 to use this compression
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_cistatic int jffs2_is_best_compression(struct jffs2_compressor *this,
3562306a36Sopenharmony_ci		struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	switch (jffs2_compression_mode) {
3862306a36Sopenharmony_ci	case JFFS2_COMPR_MODE_SIZE:
3962306a36Sopenharmony_ci		if (bestsize > size)
4062306a36Sopenharmony_ci			return 1;
4162306a36Sopenharmony_ci		return 0;
4262306a36Sopenharmony_ci	case JFFS2_COMPR_MODE_FAVOURLZO:
4362306a36Sopenharmony_ci		if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
4462306a36Sopenharmony_ci			return 1;
4562306a36Sopenharmony_ci		if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
4662306a36Sopenharmony_ci			return 1;
4762306a36Sopenharmony_ci		if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
4862306a36Sopenharmony_ci			return 1;
4962306a36Sopenharmony_ci		if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
5062306a36Sopenharmony_ci			return 1;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci		return 0;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci	/* Shouldn't happen */
5562306a36Sopenharmony_ci	return 0;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/*
5962306a36Sopenharmony_ci * jffs2_selected_compress:
6062306a36Sopenharmony_ci * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
6162306a36Sopenharmony_ci *	If 0, just take the first available compression mode.
6262306a36Sopenharmony_ci * @data_in: Pointer to uncompressed data
6362306a36Sopenharmony_ci * @cpage_out: Pointer to returned pointer to buffer for compressed data
6462306a36Sopenharmony_ci * @datalen: On entry, holds the amount of data available for compression.
6562306a36Sopenharmony_ci *	On exit, expected to hold the amount of data actually compressed.
6662306a36Sopenharmony_ci * @cdatalen: On entry, holds the amount of space available for compressed
6762306a36Sopenharmony_ci *	data. On exit, expected to hold the actual size of the compressed
6862306a36Sopenharmony_ci *	data.
6962306a36Sopenharmony_ci *
7062306a36Sopenharmony_ci * Returns: the compression type used.  Zero is used to show that the data
7162306a36Sopenharmony_ci * could not be compressed; probably because we couldn't find the requested
7262306a36Sopenharmony_ci * compression mode.
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_cistatic int jffs2_selected_compress(u8 compr, unsigned char *data_in,
7562306a36Sopenharmony_ci		unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	struct jffs2_compressor *this;
7862306a36Sopenharmony_ci	int err, ret = JFFS2_COMPR_NONE;
7962306a36Sopenharmony_ci	uint32_t orig_slen, orig_dlen;
8062306a36Sopenharmony_ci	char *output_buf;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	output_buf = kmalloc(*cdatalen, GFP_KERNEL);
8362306a36Sopenharmony_ci	if (!output_buf) {
8462306a36Sopenharmony_ci		pr_warn("No memory for compressor allocation. Compression failed.\n");
8562306a36Sopenharmony_ci		return ret;
8662306a36Sopenharmony_ci	}
8762306a36Sopenharmony_ci	orig_slen = *datalen;
8862306a36Sopenharmony_ci	orig_dlen = *cdatalen;
8962306a36Sopenharmony_ci	spin_lock(&jffs2_compressor_list_lock);
9062306a36Sopenharmony_ci	list_for_each_entry(this, &jffs2_compressor_list, list) {
9162306a36Sopenharmony_ci		/* Skip decompress-only and disabled modules */
9262306a36Sopenharmony_ci		if (!this->compress || this->disabled)
9362306a36Sopenharmony_ci			continue;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci		/* Skip if not the desired compression type */
9662306a36Sopenharmony_ci		if (compr && (compr != this->compr))
9762306a36Sopenharmony_ci			continue;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci		/*
10062306a36Sopenharmony_ci		 * Either compression type was unspecified, or we found our
10162306a36Sopenharmony_ci		 * compressor; either way, we're good to go.
10262306a36Sopenharmony_ci		 */
10362306a36Sopenharmony_ci		this->usecount++;
10462306a36Sopenharmony_ci		spin_unlock(&jffs2_compressor_list_lock);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci		*datalen  = orig_slen;
10762306a36Sopenharmony_ci		*cdatalen = orig_dlen;
10862306a36Sopenharmony_ci		err = this->compress(data_in, output_buf, datalen, cdatalen);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci		spin_lock(&jffs2_compressor_list_lock);
11162306a36Sopenharmony_ci		this->usecount--;
11262306a36Sopenharmony_ci		if (!err) {
11362306a36Sopenharmony_ci			/* Success */
11462306a36Sopenharmony_ci			ret = this->compr;
11562306a36Sopenharmony_ci			this->stat_compr_blocks++;
11662306a36Sopenharmony_ci			this->stat_compr_orig_size += *datalen;
11762306a36Sopenharmony_ci			this->stat_compr_new_size += *cdatalen;
11862306a36Sopenharmony_ci			break;
11962306a36Sopenharmony_ci		}
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci	spin_unlock(&jffs2_compressor_list_lock);
12262306a36Sopenharmony_ci	if (ret == JFFS2_COMPR_NONE)
12362306a36Sopenharmony_ci		kfree(output_buf);
12462306a36Sopenharmony_ci	else
12562306a36Sopenharmony_ci		*cpage_out = output_buf;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return ret;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/* jffs2_compress:
13162306a36Sopenharmony_ci * @data_in: Pointer to uncompressed data
13262306a36Sopenharmony_ci * @cpage_out: Pointer to returned pointer to buffer for compressed data
13362306a36Sopenharmony_ci * @datalen: On entry, holds the amount of data available for compression.
13462306a36Sopenharmony_ci *	On exit, expected to hold the amount of data actually compressed.
13562306a36Sopenharmony_ci * @cdatalen: On entry, holds the amount of space available for compressed
13662306a36Sopenharmony_ci *	data. On exit, expected to hold the actual size of the compressed
13762306a36Sopenharmony_ci *	data.
13862306a36Sopenharmony_ci *
13962306a36Sopenharmony_ci * Returns: Lower byte to be stored with data indicating compression type used.
14062306a36Sopenharmony_ci * Zero is used to show that the data could not be compressed - the
14162306a36Sopenharmony_ci * compressed version was actually larger than the original.
14262306a36Sopenharmony_ci * Upper byte will be used later. (soon)
14362306a36Sopenharmony_ci *
14462306a36Sopenharmony_ci * If the cdata buffer isn't large enough to hold all the uncompressed data,
14562306a36Sopenharmony_ci * jffs2_compress should compress as much as will fit, and should set
14662306a36Sopenharmony_ci * *datalen accordingly to show the amount of data which were compressed.
14762306a36Sopenharmony_ci */
14862306a36Sopenharmony_ciuint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
14962306a36Sopenharmony_ci			unsigned char *data_in, unsigned char **cpage_out,
15062306a36Sopenharmony_ci			uint32_t *datalen, uint32_t *cdatalen)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	int ret = JFFS2_COMPR_NONE;
15362306a36Sopenharmony_ci	int mode, compr_ret;
15462306a36Sopenharmony_ci	struct jffs2_compressor *this, *best=NULL;
15562306a36Sopenharmony_ci	unsigned char *output_buf = NULL, *tmp_buf;
15662306a36Sopenharmony_ci	uint32_t orig_slen, orig_dlen;
15762306a36Sopenharmony_ci	uint32_t best_slen=0, best_dlen=0;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	if (c->mount_opts.override_compr)
16062306a36Sopenharmony_ci		mode = c->mount_opts.compr;
16162306a36Sopenharmony_ci	else
16262306a36Sopenharmony_ci		mode = jffs2_compression_mode;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	switch (mode) {
16562306a36Sopenharmony_ci	case JFFS2_COMPR_MODE_NONE:
16662306a36Sopenharmony_ci		break;
16762306a36Sopenharmony_ci	case JFFS2_COMPR_MODE_PRIORITY:
16862306a36Sopenharmony_ci		ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
16962306a36Sopenharmony_ci				cdatalen);
17062306a36Sopenharmony_ci		break;
17162306a36Sopenharmony_ci	case JFFS2_COMPR_MODE_SIZE:
17262306a36Sopenharmony_ci	case JFFS2_COMPR_MODE_FAVOURLZO:
17362306a36Sopenharmony_ci		orig_slen = *datalen;
17462306a36Sopenharmony_ci		orig_dlen = *cdatalen;
17562306a36Sopenharmony_ci		spin_lock(&jffs2_compressor_list_lock);
17662306a36Sopenharmony_ci		list_for_each_entry(this, &jffs2_compressor_list, list) {
17762306a36Sopenharmony_ci			/* Skip decompress-only backwards-compatibility and disabled modules */
17862306a36Sopenharmony_ci			if ((!this->compress)||(this->disabled))
17962306a36Sopenharmony_ci				continue;
18062306a36Sopenharmony_ci			/* Allocating memory for output buffer if necessary */
18162306a36Sopenharmony_ci			if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
18262306a36Sopenharmony_ci				spin_unlock(&jffs2_compressor_list_lock);
18362306a36Sopenharmony_ci				kfree(this->compr_buf);
18462306a36Sopenharmony_ci				spin_lock(&jffs2_compressor_list_lock);
18562306a36Sopenharmony_ci				this->compr_buf_size=0;
18662306a36Sopenharmony_ci				this->compr_buf=NULL;
18762306a36Sopenharmony_ci			}
18862306a36Sopenharmony_ci			if (!this->compr_buf) {
18962306a36Sopenharmony_ci				spin_unlock(&jffs2_compressor_list_lock);
19062306a36Sopenharmony_ci				tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
19162306a36Sopenharmony_ci				spin_lock(&jffs2_compressor_list_lock);
19262306a36Sopenharmony_ci				if (!tmp_buf) {
19362306a36Sopenharmony_ci					pr_warn("No memory for compressor allocation. (%d bytes)\n",
19462306a36Sopenharmony_ci						orig_slen);
19562306a36Sopenharmony_ci					continue;
19662306a36Sopenharmony_ci				}
19762306a36Sopenharmony_ci				else {
19862306a36Sopenharmony_ci					this->compr_buf = tmp_buf;
19962306a36Sopenharmony_ci					this->compr_buf_size = orig_slen;
20062306a36Sopenharmony_ci				}
20162306a36Sopenharmony_ci			}
20262306a36Sopenharmony_ci			this->usecount++;
20362306a36Sopenharmony_ci			spin_unlock(&jffs2_compressor_list_lock);
20462306a36Sopenharmony_ci			*datalen  = orig_slen;
20562306a36Sopenharmony_ci			*cdatalen = orig_dlen;
20662306a36Sopenharmony_ci			compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
20762306a36Sopenharmony_ci			spin_lock(&jffs2_compressor_list_lock);
20862306a36Sopenharmony_ci			this->usecount--;
20962306a36Sopenharmony_ci			if (!compr_ret) {
21062306a36Sopenharmony_ci				if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
21162306a36Sopenharmony_ci						&& (*cdatalen < *datalen)) {
21262306a36Sopenharmony_ci					best_dlen = *cdatalen;
21362306a36Sopenharmony_ci					best_slen = *datalen;
21462306a36Sopenharmony_ci					best = this;
21562306a36Sopenharmony_ci				}
21662306a36Sopenharmony_ci			}
21762306a36Sopenharmony_ci		}
21862306a36Sopenharmony_ci		if (best_dlen) {
21962306a36Sopenharmony_ci			*cdatalen = best_dlen;
22062306a36Sopenharmony_ci			*datalen  = best_slen;
22162306a36Sopenharmony_ci			output_buf = best->compr_buf;
22262306a36Sopenharmony_ci			best->compr_buf = NULL;
22362306a36Sopenharmony_ci			best->compr_buf_size = 0;
22462306a36Sopenharmony_ci			best->stat_compr_blocks++;
22562306a36Sopenharmony_ci			best->stat_compr_orig_size += best_slen;
22662306a36Sopenharmony_ci			best->stat_compr_new_size  += best_dlen;
22762306a36Sopenharmony_ci			ret = best->compr;
22862306a36Sopenharmony_ci			*cpage_out = output_buf;
22962306a36Sopenharmony_ci		}
23062306a36Sopenharmony_ci		spin_unlock(&jffs2_compressor_list_lock);
23162306a36Sopenharmony_ci		break;
23262306a36Sopenharmony_ci	case JFFS2_COMPR_MODE_FORCELZO:
23362306a36Sopenharmony_ci		ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
23462306a36Sopenharmony_ci				cpage_out, datalen, cdatalen);
23562306a36Sopenharmony_ci		break;
23662306a36Sopenharmony_ci	case JFFS2_COMPR_MODE_FORCEZLIB:
23762306a36Sopenharmony_ci		ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
23862306a36Sopenharmony_ci				cpage_out, datalen, cdatalen);
23962306a36Sopenharmony_ci		break;
24062306a36Sopenharmony_ci	default:
24162306a36Sopenharmony_ci		pr_err("unknown compression mode\n");
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	if (ret == JFFS2_COMPR_NONE) {
24562306a36Sopenharmony_ci		*cpage_out = data_in;
24662306a36Sopenharmony_ci		*datalen = *cdatalen;
24762306a36Sopenharmony_ci		none_stat_compr_blocks++;
24862306a36Sopenharmony_ci		none_stat_compr_size += *datalen;
24962306a36Sopenharmony_ci	}
25062306a36Sopenharmony_ci	return ret;
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ciint jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
25462306a36Sopenharmony_ci		     uint16_t comprtype, unsigned char *cdata_in,
25562306a36Sopenharmony_ci		     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
25662306a36Sopenharmony_ci{
25762306a36Sopenharmony_ci	struct jffs2_compressor *this;
25862306a36Sopenharmony_ci	int ret;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	/* Older code had a bug where it would write non-zero 'usercompr'
26162306a36Sopenharmony_ci	   fields. Deal with it. */
26262306a36Sopenharmony_ci	if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB)
26362306a36Sopenharmony_ci		comprtype &= 0xff;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	switch (comprtype & 0xff) {
26662306a36Sopenharmony_ci	case JFFS2_COMPR_NONE:
26762306a36Sopenharmony_ci		/* This should be special-cased elsewhere, but we might as well deal with it */
26862306a36Sopenharmony_ci		memcpy(data_out, cdata_in, datalen);
26962306a36Sopenharmony_ci		none_stat_decompr_blocks++;
27062306a36Sopenharmony_ci		break;
27162306a36Sopenharmony_ci	case JFFS2_COMPR_ZERO:
27262306a36Sopenharmony_ci		memset(data_out, 0, datalen);
27362306a36Sopenharmony_ci		break;
27462306a36Sopenharmony_ci	default:
27562306a36Sopenharmony_ci		spin_lock(&jffs2_compressor_list_lock);
27662306a36Sopenharmony_ci		list_for_each_entry(this, &jffs2_compressor_list, list) {
27762306a36Sopenharmony_ci			if (comprtype == this->compr) {
27862306a36Sopenharmony_ci				this->usecount++;
27962306a36Sopenharmony_ci				spin_unlock(&jffs2_compressor_list_lock);
28062306a36Sopenharmony_ci				ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
28162306a36Sopenharmony_ci				spin_lock(&jffs2_compressor_list_lock);
28262306a36Sopenharmony_ci				if (ret) {
28362306a36Sopenharmony_ci					pr_warn("Decompressor \"%s\" returned %d\n",
28462306a36Sopenharmony_ci						this->name, ret);
28562306a36Sopenharmony_ci				}
28662306a36Sopenharmony_ci				else {
28762306a36Sopenharmony_ci					this->stat_decompr_blocks++;
28862306a36Sopenharmony_ci				}
28962306a36Sopenharmony_ci				this->usecount--;
29062306a36Sopenharmony_ci				spin_unlock(&jffs2_compressor_list_lock);
29162306a36Sopenharmony_ci				return ret;
29262306a36Sopenharmony_ci			}
29362306a36Sopenharmony_ci		}
29462306a36Sopenharmony_ci		pr_warn("compression type 0x%02x not available\n", comprtype);
29562306a36Sopenharmony_ci		spin_unlock(&jffs2_compressor_list_lock);
29662306a36Sopenharmony_ci		return -EIO;
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci	return 0;
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ciint jffs2_register_compressor(struct jffs2_compressor *comp)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	struct jffs2_compressor *this;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	if (!comp->name) {
30662306a36Sopenharmony_ci		pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n");
30762306a36Sopenharmony_ci		return -1;
30862306a36Sopenharmony_ci	}
30962306a36Sopenharmony_ci	comp->compr_buf_size=0;
31062306a36Sopenharmony_ci	comp->compr_buf=NULL;
31162306a36Sopenharmony_ci	comp->usecount=0;
31262306a36Sopenharmony_ci	comp->stat_compr_orig_size=0;
31362306a36Sopenharmony_ci	comp->stat_compr_new_size=0;
31462306a36Sopenharmony_ci	comp->stat_compr_blocks=0;
31562306a36Sopenharmony_ci	comp->stat_decompr_blocks=0;
31662306a36Sopenharmony_ci	jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	spin_lock(&jffs2_compressor_list_lock);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	list_for_each_entry(this, &jffs2_compressor_list, list) {
32162306a36Sopenharmony_ci		if (this->priority < comp->priority) {
32262306a36Sopenharmony_ci			list_add(&comp->list, this->list.prev);
32362306a36Sopenharmony_ci			goto out;
32462306a36Sopenharmony_ci		}
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci	list_add_tail(&comp->list, &jffs2_compressor_list);
32762306a36Sopenharmony_ciout:
32862306a36Sopenharmony_ci	D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
32962306a36Sopenharmony_ci		printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
33062306a36Sopenharmony_ci	})
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	spin_unlock(&jffs2_compressor_list_lock);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	return 0;
33562306a36Sopenharmony_ci}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ciint jffs2_unregister_compressor(struct jffs2_compressor *comp)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	D2(struct jffs2_compressor *this);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name);
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	spin_lock(&jffs2_compressor_list_lock);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	if (comp->usecount) {
34662306a36Sopenharmony_ci		spin_unlock(&jffs2_compressor_list_lock);
34762306a36Sopenharmony_ci		pr_warn("Compressor module is in use. Unregister failed.\n");
34862306a36Sopenharmony_ci		return -1;
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci	list_del(&comp->list);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
35362306a36Sopenharmony_ci		printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
35462306a36Sopenharmony_ci	})
35562306a36Sopenharmony_ci	spin_unlock(&jffs2_compressor_list_lock);
35662306a36Sopenharmony_ci	return 0;
35762306a36Sopenharmony_ci}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_civoid jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
36062306a36Sopenharmony_ci{
36162306a36Sopenharmony_ci	if (orig != comprbuf)
36262306a36Sopenharmony_ci		kfree(comprbuf);
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ciint __init jffs2_compressors_init(void)
36662306a36Sopenharmony_ci{
36762306a36Sopenharmony_ci	int ret = 0;
36862306a36Sopenharmony_ci/* Registering compressors */
36962306a36Sopenharmony_ci	ret = jffs2_zlib_init();
37062306a36Sopenharmony_ci	if (ret)
37162306a36Sopenharmony_ci		goto exit;
37262306a36Sopenharmony_ci	ret = jffs2_rtime_init();
37362306a36Sopenharmony_ci	if (ret)
37462306a36Sopenharmony_ci		goto exit_zlib;
37562306a36Sopenharmony_ci	ret = jffs2_rubinmips_init();
37662306a36Sopenharmony_ci	if (ret)
37762306a36Sopenharmony_ci		goto exit_rtime;
37862306a36Sopenharmony_ci	ret = jffs2_dynrubin_init();
37962306a36Sopenharmony_ci	if (ret)
38062306a36Sopenharmony_ci		goto exit_runinmips;
38162306a36Sopenharmony_ci	ret = jffs2_lzo_init();
38262306a36Sopenharmony_ci	if (ret)
38362306a36Sopenharmony_ci		goto exit_dynrubin;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci/* Setting default compression mode */
38762306a36Sopenharmony_ci#ifdef CONFIG_JFFS2_CMODE_NONE
38862306a36Sopenharmony_ci	jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
38962306a36Sopenharmony_ci	jffs2_dbg(1, "default compression mode: none\n");
39062306a36Sopenharmony_ci#else
39162306a36Sopenharmony_ci#ifdef CONFIG_JFFS2_CMODE_SIZE
39262306a36Sopenharmony_ci	jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
39362306a36Sopenharmony_ci	jffs2_dbg(1, "default compression mode: size\n");
39462306a36Sopenharmony_ci#else
39562306a36Sopenharmony_ci#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
39662306a36Sopenharmony_ci	jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
39762306a36Sopenharmony_ci	jffs2_dbg(1, "default compression mode: favourlzo\n");
39862306a36Sopenharmony_ci#else
39962306a36Sopenharmony_ci	jffs2_dbg(1, "default compression mode: priority\n");
40062306a36Sopenharmony_ci#endif
40162306a36Sopenharmony_ci#endif
40262306a36Sopenharmony_ci#endif
40362306a36Sopenharmony_ci	return 0;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ciexit_dynrubin:
40662306a36Sopenharmony_ci	jffs2_dynrubin_exit();
40762306a36Sopenharmony_ciexit_runinmips:
40862306a36Sopenharmony_ci	jffs2_rubinmips_exit();
40962306a36Sopenharmony_ciexit_rtime:
41062306a36Sopenharmony_ci	jffs2_rtime_exit();
41162306a36Sopenharmony_ciexit_zlib:
41262306a36Sopenharmony_ci	jffs2_zlib_exit();
41362306a36Sopenharmony_ciexit:
41462306a36Sopenharmony_ci	return ret;
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ciint jffs2_compressors_exit(void)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci/* Unregistering compressors */
42062306a36Sopenharmony_ci	jffs2_lzo_exit();
42162306a36Sopenharmony_ci	jffs2_dynrubin_exit();
42262306a36Sopenharmony_ci	jffs2_rubinmips_exit();
42362306a36Sopenharmony_ci	jffs2_rtime_exit();
42462306a36Sopenharmony_ci	jffs2_zlib_exit();
42562306a36Sopenharmony_ci	return 0;
42662306a36Sopenharmony_ci}
427