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