18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc.
58c2ecf20Sopenharmony_ci * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
68c2ecf20Sopenharmony_ci * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
78c2ecf20Sopenharmony_ci *		    University of Szeged, Hungary
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Created by Arjan van de Ven <arjan@infradead.org>
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "compr.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(jffs2_compressor_list_lock);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/* Available compressors are on this list */
228c2ecf20Sopenharmony_cistatic LIST_HEAD(jffs2_compressor_list);
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/* Actual compression mode */
258c2ecf20Sopenharmony_cistatic int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* Statistics for blocks stored without compression */
288c2ecf20Sopenharmony_cistatic uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/*
328c2ecf20Sopenharmony_ci * Return 1 to use this compression
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_cistatic int jffs2_is_best_compression(struct jffs2_compressor *this,
358c2ecf20Sopenharmony_ci		struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	switch (jffs2_compression_mode) {
388c2ecf20Sopenharmony_ci	case JFFS2_COMPR_MODE_SIZE:
398c2ecf20Sopenharmony_ci		if (bestsize > size)
408c2ecf20Sopenharmony_ci			return 1;
418c2ecf20Sopenharmony_ci		return 0;
428c2ecf20Sopenharmony_ci	case JFFS2_COMPR_MODE_FAVOURLZO:
438c2ecf20Sopenharmony_ci		if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
448c2ecf20Sopenharmony_ci			return 1;
458c2ecf20Sopenharmony_ci		if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
468c2ecf20Sopenharmony_ci			return 1;
478c2ecf20Sopenharmony_ci		if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
488c2ecf20Sopenharmony_ci			return 1;
498c2ecf20Sopenharmony_ci		if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
508c2ecf20Sopenharmony_ci			return 1;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci		return 0;
538c2ecf20Sopenharmony_ci	}
548c2ecf20Sopenharmony_ci	/* Shouldn't happen */
558c2ecf20Sopenharmony_ci	return 0;
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/*
598c2ecf20Sopenharmony_ci * jffs2_selected_compress:
608c2ecf20Sopenharmony_ci * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
618c2ecf20Sopenharmony_ci *	If 0, just take the first available compression mode.
628c2ecf20Sopenharmony_ci * @data_in: Pointer to uncompressed data
638c2ecf20Sopenharmony_ci * @cpage_out: Pointer to returned pointer to buffer for compressed data
648c2ecf20Sopenharmony_ci * @datalen: On entry, holds the amount of data available for compression.
658c2ecf20Sopenharmony_ci *	On exit, expected to hold the amount of data actually compressed.
668c2ecf20Sopenharmony_ci * @cdatalen: On entry, holds the amount of space available for compressed
678c2ecf20Sopenharmony_ci *	data. On exit, expected to hold the actual size of the compressed
688c2ecf20Sopenharmony_ci *	data.
698c2ecf20Sopenharmony_ci *
708c2ecf20Sopenharmony_ci * Returns: the compression type used.  Zero is used to show that the data
718c2ecf20Sopenharmony_ci * could not be compressed; probably because we couldn't find the requested
728c2ecf20Sopenharmony_ci * compression mode.
738c2ecf20Sopenharmony_ci */
748c2ecf20Sopenharmony_cistatic int jffs2_selected_compress(u8 compr, unsigned char *data_in,
758c2ecf20Sopenharmony_ci		unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	struct jffs2_compressor *this;
788c2ecf20Sopenharmony_ci	int err, ret = JFFS2_COMPR_NONE;
798c2ecf20Sopenharmony_ci	uint32_t orig_slen, orig_dlen;
808c2ecf20Sopenharmony_ci	char *output_buf;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	output_buf = kmalloc(*cdatalen, GFP_KERNEL);
838c2ecf20Sopenharmony_ci	if (!output_buf) {
848c2ecf20Sopenharmony_ci		pr_warn("No memory for compressor allocation. Compression failed.\n");
858c2ecf20Sopenharmony_ci		return ret;
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci	orig_slen = *datalen;
888c2ecf20Sopenharmony_ci	orig_dlen = *cdatalen;
898c2ecf20Sopenharmony_ci	spin_lock(&jffs2_compressor_list_lock);
908c2ecf20Sopenharmony_ci	list_for_each_entry(this, &jffs2_compressor_list, list) {
918c2ecf20Sopenharmony_ci		/* Skip decompress-only and disabled modules */
928c2ecf20Sopenharmony_ci		if (!this->compress || this->disabled)
938c2ecf20Sopenharmony_ci			continue;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci		/* Skip if not the desired compression type */
968c2ecf20Sopenharmony_ci		if (compr && (compr != this->compr))
978c2ecf20Sopenharmony_ci			continue;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci		/*
1008c2ecf20Sopenharmony_ci		 * Either compression type was unspecified, or we found our
1018c2ecf20Sopenharmony_ci		 * compressor; either way, we're good to go.
1028c2ecf20Sopenharmony_ci		 */
1038c2ecf20Sopenharmony_ci		this->usecount++;
1048c2ecf20Sopenharmony_ci		spin_unlock(&jffs2_compressor_list_lock);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci		*datalen  = orig_slen;
1078c2ecf20Sopenharmony_ci		*cdatalen = orig_dlen;
1088c2ecf20Sopenharmony_ci		err = this->compress(data_in, output_buf, datalen, cdatalen);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci		spin_lock(&jffs2_compressor_list_lock);
1118c2ecf20Sopenharmony_ci		this->usecount--;
1128c2ecf20Sopenharmony_ci		if (!err) {
1138c2ecf20Sopenharmony_ci			/* Success */
1148c2ecf20Sopenharmony_ci			ret = this->compr;
1158c2ecf20Sopenharmony_ci			this->stat_compr_blocks++;
1168c2ecf20Sopenharmony_ci			this->stat_compr_orig_size += *datalen;
1178c2ecf20Sopenharmony_ci			this->stat_compr_new_size += *cdatalen;
1188c2ecf20Sopenharmony_ci			break;
1198c2ecf20Sopenharmony_ci		}
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci	spin_unlock(&jffs2_compressor_list_lock);
1228c2ecf20Sopenharmony_ci	if (ret == JFFS2_COMPR_NONE)
1238c2ecf20Sopenharmony_ci		kfree(output_buf);
1248c2ecf20Sopenharmony_ci	else
1258c2ecf20Sopenharmony_ci		*cpage_out = output_buf;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	return ret;
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci/* jffs2_compress:
1318c2ecf20Sopenharmony_ci * @data_in: Pointer to uncompressed data
1328c2ecf20Sopenharmony_ci * @cpage_out: Pointer to returned pointer to buffer for compressed data
1338c2ecf20Sopenharmony_ci * @datalen: On entry, holds the amount of data available for compression.
1348c2ecf20Sopenharmony_ci *	On exit, expected to hold the amount of data actually compressed.
1358c2ecf20Sopenharmony_ci * @cdatalen: On entry, holds the amount of space available for compressed
1368c2ecf20Sopenharmony_ci *	data. On exit, expected to hold the actual size of the compressed
1378c2ecf20Sopenharmony_ci *	data.
1388c2ecf20Sopenharmony_ci *
1398c2ecf20Sopenharmony_ci * Returns: Lower byte to be stored with data indicating compression type used.
1408c2ecf20Sopenharmony_ci * Zero is used to show that the data could not be compressed - the
1418c2ecf20Sopenharmony_ci * compressed version was actually larger than the original.
1428c2ecf20Sopenharmony_ci * Upper byte will be used later. (soon)
1438c2ecf20Sopenharmony_ci *
1448c2ecf20Sopenharmony_ci * If the cdata buffer isn't large enough to hold all the uncompressed data,
1458c2ecf20Sopenharmony_ci * jffs2_compress should compress as much as will fit, and should set
1468c2ecf20Sopenharmony_ci * *datalen accordingly to show the amount of data which were compressed.
1478c2ecf20Sopenharmony_ci */
1488c2ecf20Sopenharmony_ciuint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
1498c2ecf20Sopenharmony_ci			unsigned char *data_in, unsigned char **cpage_out,
1508c2ecf20Sopenharmony_ci			uint32_t *datalen, uint32_t *cdatalen)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	int ret = JFFS2_COMPR_NONE;
1538c2ecf20Sopenharmony_ci	int mode, compr_ret;
1548c2ecf20Sopenharmony_ci	struct jffs2_compressor *this, *best=NULL;
1558c2ecf20Sopenharmony_ci	unsigned char *output_buf = NULL, *tmp_buf;
1568c2ecf20Sopenharmony_ci	uint32_t orig_slen, orig_dlen;
1578c2ecf20Sopenharmony_ci	uint32_t best_slen=0, best_dlen=0;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	if (c->mount_opts.override_compr)
1608c2ecf20Sopenharmony_ci		mode = c->mount_opts.compr;
1618c2ecf20Sopenharmony_ci	else
1628c2ecf20Sopenharmony_ci		mode = jffs2_compression_mode;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	switch (mode) {
1658c2ecf20Sopenharmony_ci	case JFFS2_COMPR_MODE_NONE:
1668c2ecf20Sopenharmony_ci		break;
1678c2ecf20Sopenharmony_ci	case JFFS2_COMPR_MODE_PRIORITY:
1688c2ecf20Sopenharmony_ci		ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
1698c2ecf20Sopenharmony_ci				cdatalen);
1708c2ecf20Sopenharmony_ci		break;
1718c2ecf20Sopenharmony_ci	case JFFS2_COMPR_MODE_SIZE:
1728c2ecf20Sopenharmony_ci	case JFFS2_COMPR_MODE_FAVOURLZO:
1738c2ecf20Sopenharmony_ci		orig_slen = *datalen;
1748c2ecf20Sopenharmony_ci		orig_dlen = *cdatalen;
1758c2ecf20Sopenharmony_ci		spin_lock(&jffs2_compressor_list_lock);
1768c2ecf20Sopenharmony_ci		list_for_each_entry(this, &jffs2_compressor_list, list) {
1778c2ecf20Sopenharmony_ci			/* Skip decompress-only backwards-compatibility and disabled modules */
1788c2ecf20Sopenharmony_ci			if ((!this->compress)||(this->disabled))
1798c2ecf20Sopenharmony_ci				continue;
1808c2ecf20Sopenharmony_ci			/* Allocating memory for output buffer if necessary */
1818c2ecf20Sopenharmony_ci			if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
1828c2ecf20Sopenharmony_ci				spin_unlock(&jffs2_compressor_list_lock);
1838c2ecf20Sopenharmony_ci				kfree(this->compr_buf);
1848c2ecf20Sopenharmony_ci				spin_lock(&jffs2_compressor_list_lock);
1858c2ecf20Sopenharmony_ci				this->compr_buf_size=0;
1868c2ecf20Sopenharmony_ci				this->compr_buf=NULL;
1878c2ecf20Sopenharmony_ci			}
1888c2ecf20Sopenharmony_ci			if (!this->compr_buf) {
1898c2ecf20Sopenharmony_ci				spin_unlock(&jffs2_compressor_list_lock);
1908c2ecf20Sopenharmony_ci				tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
1918c2ecf20Sopenharmony_ci				spin_lock(&jffs2_compressor_list_lock);
1928c2ecf20Sopenharmony_ci				if (!tmp_buf) {
1938c2ecf20Sopenharmony_ci					pr_warn("No memory for compressor allocation. (%d bytes)\n",
1948c2ecf20Sopenharmony_ci						orig_slen);
1958c2ecf20Sopenharmony_ci					continue;
1968c2ecf20Sopenharmony_ci				}
1978c2ecf20Sopenharmony_ci				else {
1988c2ecf20Sopenharmony_ci					this->compr_buf = tmp_buf;
1998c2ecf20Sopenharmony_ci					this->compr_buf_size = orig_slen;
2008c2ecf20Sopenharmony_ci				}
2018c2ecf20Sopenharmony_ci			}
2028c2ecf20Sopenharmony_ci			this->usecount++;
2038c2ecf20Sopenharmony_ci			spin_unlock(&jffs2_compressor_list_lock);
2048c2ecf20Sopenharmony_ci			*datalen  = orig_slen;
2058c2ecf20Sopenharmony_ci			*cdatalen = orig_dlen;
2068c2ecf20Sopenharmony_ci			compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
2078c2ecf20Sopenharmony_ci			spin_lock(&jffs2_compressor_list_lock);
2088c2ecf20Sopenharmony_ci			this->usecount--;
2098c2ecf20Sopenharmony_ci			if (!compr_ret) {
2108c2ecf20Sopenharmony_ci				if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
2118c2ecf20Sopenharmony_ci						&& (*cdatalen < *datalen)) {
2128c2ecf20Sopenharmony_ci					best_dlen = *cdatalen;
2138c2ecf20Sopenharmony_ci					best_slen = *datalen;
2148c2ecf20Sopenharmony_ci					best = this;
2158c2ecf20Sopenharmony_ci				}
2168c2ecf20Sopenharmony_ci			}
2178c2ecf20Sopenharmony_ci		}
2188c2ecf20Sopenharmony_ci		if (best_dlen) {
2198c2ecf20Sopenharmony_ci			*cdatalen = best_dlen;
2208c2ecf20Sopenharmony_ci			*datalen  = best_slen;
2218c2ecf20Sopenharmony_ci			output_buf = best->compr_buf;
2228c2ecf20Sopenharmony_ci			best->compr_buf = NULL;
2238c2ecf20Sopenharmony_ci			best->compr_buf_size = 0;
2248c2ecf20Sopenharmony_ci			best->stat_compr_blocks++;
2258c2ecf20Sopenharmony_ci			best->stat_compr_orig_size += best_slen;
2268c2ecf20Sopenharmony_ci			best->stat_compr_new_size  += best_dlen;
2278c2ecf20Sopenharmony_ci			ret = best->compr;
2288c2ecf20Sopenharmony_ci			*cpage_out = output_buf;
2298c2ecf20Sopenharmony_ci		}
2308c2ecf20Sopenharmony_ci		spin_unlock(&jffs2_compressor_list_lock);
2318c2ecf20Sopenharmony_ci		break;
2328c2ecf20Sopenharmony_ci	case JFFS2_COMPR_MODE_FORCELZO:
2338c2ecf20Sopenharmony_ci		ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
2348c2ecf20Sopenharmony_ci				cpage_out, datalen, cdatalen);
2358c2ecf20Sopenharmony_ci		break;
2368c2ecf20Sopenharmony_ci	case JFFS2_COMPR_MODE_FORCEZLIB:
2378c2ecf20Sopenharmony_ci		ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
2388c2ecf20Sopenharmony_ci				cpage_out, datalen, cdatalen);
2398c2ecf20Sopenharmony_ci		break;
2408c2ecf20Sopenharmony_ci	default:
2418c2ecf20Sopenharmony_ci		pr_err("unknown compression mode\n");
2428c2ecf20Sopenharmony_ci	}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (ret == JFFS2_COMPR_NONE) {
2458c2ecf20Sopenharmony_ci		*cpage_out = data_in;
2468c2ecf20Sopenharmony_ci		*datalen = *cdatalen;
2478c2ecf20Sopenharmony_ci		none_stat_compr_blocks++;
2488c2ecf20Sopenharmony_ci		none_stat_compr_size += *datalen;
2498c2ecf20Sopenharmony_ci	}
2508c2ecf20Sopenharmony_ci	return ret;
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ciint jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
2548c2ecf20Sopenharmony_ci		     uint16_t comprtype, unsigned char *cdata_in,
2558c2ecf20Sopenharmony_ci		     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	struct jffs2_compressor *this;
2588c2ecf20Sopenharmony_ci	int ret;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	/* Older code had a bug where it would write non-zero 'usercompr'
2618c2ecf20Sopenharmony_ci	   fields. Deal with it. */
2628c2ecf20Sopenharmony_ci	if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB)
2638c2ecf20Sopenharmony_ci		comprtype &= 0xff;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	switch (comprtype & 0xff) {
2668c2ecf20Sopenharmony_ci	case JFFS2_COMPR_NONE:
2678c2ecf20Sopenharmony_ci		/* This should be special-cased elsewhere, but we might as well deal with it */
2688c2ecf20Sopenharmony_ci		memcpy(data_out, cdata_in, datalen);
2698c2ecf20Sopenharmony_ci		none_stat_decompr_blocks++;
2708c2ecf20Sopenharmony_ci		break;
2718c2ecf20Sopenharmony_ci	case JFFS2_COMPR_ZERO:
2728c2ecf20Sopenharmony_ci		memset(data_out, 0, datalen);
2738c2ecf20Sopenharmony_ci		break;
2748c2ecf20Sopenharmony_ci	default:
2758c2ecf20Sopenharmony_ci		spin_lock(&jffs2_compressor_list_lock);
2768c2ecf20Sopenharmony_ci		list_for_each_entry(this, &jffs2_compressor_list, list) {
2778c2ecf20Sopenharmony_ci			if (comprtype == this->compr) {
2788c2ecf20Sopenharmony_ci				this->usecount++;
2798c2ecf20Sopenharmony_ci				spin_unlock(&jffs2_compressor_list_lock);
2808c2ecf20Sopenharmony_ci				ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
2818c2ecf20Sopenharmony_ci				spin_lock(&jffs2_compressor_list_lock);
2828c2ecf20Sopenharmony_ci				if (ret) {
2838c2ecf20Sopenharmony_ci					pr_warn("Decompressor \"%s\" returned %d\n",
2848c2ecf20Sopenharmony_ci						this->name, ret);
2858c2ecf20Sopenharmony_ci				}
2868c2ecf20Sopenharmony_ci				else {
2878c2ecf20Sopenharmony_ci					this->stat_decompr_blocks++;
2888c2ecf20Sopenharmony_ci				}
2898c2ecf20Sopenharmony_ci				this->usecount--;
2908c2ecf20Sopenharmony_ci				spin_unlock(&jffs2_compressor_list_lock);
2918c2ecf20Sopenharmony_ci				return ret;
2928c2ecf20Sopenharmony_ci			}
2938c2ecf20Sopenharmony_ci		}
2948c2ecf20Sopenharmony_ci		pr_warn("compression type 0x%02x not available\n", comprtype);
2958c2ecf20Sopenharmony_ci		spin_unlock(&jffs2_compressor_list_lock);
2968c2ecf20Sopenharmony_ci		return -EIO;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci	return 0;
2998c2ecf20Sopenharmony_ci}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ciint jffs2_register_compressor(struct jffs2_compressor *comp)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	struct jffs2_compressor *this;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	if (!comp->name) {
3068c2ecf20Sopenharmony_ci		pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n");
3078c2ecf20Sopenharmony_ci		return -1;
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci	comp->compr_buf_size=0;
3108c2ecf20Sopenharmony_ci	comp->compr_buf=NULL;
3118c2ecf20Sopenharmony_ci	comp->usecount=0;
3128c2ecf20Sopenharmony_ci	comp->stat_compr_orig_size=0;
3138c2ecf20Sopenharmony_ci	comp->stat_compr_new_size=0;
3148c2ecf20Sopenharmony_ci	comp->stat_compr_blocks=0;
3158c2ecf20Sopenharmony_ci	comp->stat_decompr_blocks=0;
3168c2ecf20Sopenharmony_ci	jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	spin_lock(&jffs2_compressor_list_lock);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	list_for_each_entry(this, &jffs2_compressor_list, list) {
3218c2ecf20Sopenharmony_ci		if (this->priority < comp->priority) {
3228c2ecf20Sopenharmony_ci			list_add(&comp->list, this->list.prev);
3238c2ecf20Sopenharmony_ci			goto out;
3248c2ecf20Sopenharmony_ci		}
3258c2ecf20Sopenharmony_ci	}
3268c2ecf20Sopenharmony_ci	list_add_tail(&comp->list, &jffs2_compressor_list);
3278c2ecf20Sopenharmony_ciout:
3288c2ecf20Sopenharmony_ci	D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
3298c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
3308c2ecf20Sopenharmony_ci	})
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	spin_unlock(&jffs2_compressor_list_lock);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	return 0;
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ciint jffs2_unregister_compressor(struct jffs2_compressor *comp)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci	D2(struct jffs2_compressor *this);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	spin_lock(&jffs2_compressor_list_lock);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if (comp->usecount) {
3468c2ecf20Sopenharmony_ci		spin_unlock(&jffs2_compressor_list_lock);
3478c2ecf20Sopenharmony_ci		pr_warn("Compressor module is in use. Unregister failed.\n");
3488c2ecf20Sopenharmony_ci		return -1;
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci	list_del(&comp->list);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
3538c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
3548c2ecf20Sopenharmony_ci	})
3558c2ecf20Sopenharmony_ci	spin_unlock(&jffs2_compressor_list_lock);
3568c2ecf20Sopenharmony_ci	return 0;
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_civoid jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	if (orig != comprbuf)
3628c2ecf20Sopenharmony_ci		kfree(comprbuf);
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ciint __init jffs2_compressors_init(void)
3668c2ecf20Sopenharmony_ci{
3678c2ecf20Sopenharmony_ci/* Registering compressors */
3688c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_ZLIB
3698c2ecf20Sopenharmony_ci	jffs2_zlib_init();
3708c2ecf20Sopenharmony_ci#endif
3718c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_RTIME
3728c2ecf20Sopenharmony_ci	jffs2_rtime_init();
3738c2ecf20Sopenharmony_ci#endif
3748c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_RUBIN
3758c2ecf20Sopenharmony_ci	jffs2_rubinmips_init();
3768c2ecf20Sopenharmony_ci	jffs2_dynrubin_init();
3778c2ecf20Sopenharmony_ci#endif
3788c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_LZO
3798c2ecf20Sopenharmony_ci	jffs2_lzo_init();
3808c2ecf20Sopenharmony_ci#endif
3818c2ecf20Sopenharmony_ci/* Setting default compression mode */
3828c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_CMODE_NONE
3838c2ecf20Sopenharmony_ci	jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
3848c2ecf20Sopenharmony_ci	jffs2_dbg(1, "default compression mode: none\n");
3858c2ecf20Sopenharmony_ci#else
3868c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_CMODE_SIZE
3878c2ecf20Sopenharmony_ci	jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
3888c2ecf20Sopenharmony_ci	jffs2_dbg(1, "default compression mode: size\n");
3898c2ecf20Sopenharmony_ci#else
3908c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
3918c2ecf20Sopenharmony_ci	jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
3928c2ecf20Sopenharmony_ci	jffs2_dbg(1, "default compression mode: favourlzo\n");
3938c2ecf20Sopenharmony_ci#else
3948c2ecf20Sopenharmony_ci	jffs2_dbg(1, "default compression mode: priority\n");
3958c2ecf20Sopenharmony_ci#endif
3968c2ecf20Sopenharmony_ci#endif
3978c2ecf20Sopenharmony_ci#endif
3988c2ecf20Sopenharmony_ci	return 0;
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ciint jffs2_compressors_exit(void)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci/* Unregistering compressors */
4048c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_LZO
4058c2ecf20Sopenharmony_ci	jffs2_lzo_exit();
4068c2ecf20Sopenharmony_ci#endif
4078c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_RUBIN
4088c2ecf20Sopenharmony_ci	jffs2_dynrubin_exit();
4098c2ecf20Sopenharmony_ci	jffs2_rubinmips_exit();
4108c2ecf20Sopenharmony_ci#endif
4118c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_RTIME
4128c2ecf20Sopenharmony_ci	jffs2_rtime_exit();
4138c2ecf20Sopenharmony_ci#endif
4148c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_ZLIB
4158c2ecf20Sopenharmony_ci	jffs2_zlib_exit();
4168c2ecf20Sopenharmony_ci#endif
4178c2ecf20Sopenharmony_ci	return 0;
4188c2ecf20Sopenharmony_ci}
419