11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * JFFS2 -- Journalling Flash File System, Version 2. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2001-2003 Red Hat, Inc. 51da177e4SLinus Torvalds * Created by Arjan van de Ven <arjanv@redhat.com> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 81da177e4SLinus Torvalds * University of Szeged, Hungary 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * For licensing information, see the file 'LICENCE' in this directory. 111da177e4SLinus Torvalds * 12182ec4eeSThomas Gleixner * $Id: compr.c,v 1.46 2005/11/07 11:14:38 gleixner Exp $ 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds */ 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds #include "compr.h" 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds static DEFINE_SPINLOCK(jffs2_compressor_list_lock); 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds /* Available compressors are on this list */ 211da177e4SLinus Torvalds static LIST_HEAD(jffs2_compressor_list); 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds /* Actual compression mode */ 241da177e4SLinus Torvalds static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds /* Statistics for blocks stored without compression */ 271da177e4SLinus Torvalds static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0; 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds /* jffs2_compress: 301da177e4SLinus Torvalds * @data: Pointer to uncompressed data 311da177e4SLinus Torvalds * @cdata: Pointer to returned pointer to buffer for compressed data 321da177e4SLinus Torvalds * @datalen: On entry, holds the amount of data available for compression. 331da177e4SLinus Torvalds * On exit, expected to hold the amount of data actually compressed. 341da177e4SLinus Torvalds * @cdatalen: On entry, holds the amount of space available for compressed 351da177e4SLinus Torvalds * data. On exit, expected to hold the actual size of the compressed 361da177e4SLinus Torvalds * data. 371da177e4SLinus Torvalds * 381da177e4SLinus Torvalds * Returns: Lower byte to be stored with data indicating compression type used. 391da177e4SLinus Torvalds * Zero is used to show that the data could not be compressed - the 401da177e4SLinus Torvalds * compressed version was actually larger than the original. 411da177e4SLinus Torvalds * Upper byte will be used later. (soon) 421da177e4SLinus Torvalds * 431da177e4SLinus Torvalds * If the cdata buffer isn't large enough to hold all the uncompressed data, 441da177e4SLinus Torvalds * jffs2_compress should compress as much as will fit, and should set 451da177e4SLinus Torvalds * *datalen accordingly to show the amount of data which were compressed. 461da177e4SLinus Torvalds */ 471da177e4SLinus Torvalds uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 481da177e4SLinus Torvalds unsigned char *data_in, unsigned char **cpage_out, 491da177e4SLinus Torvalds uint32_t *datalen, uint32_t *cdatalen) 501da177e4SLinus Torvalds { 511da177e4SLinus Torvalds int ret = JFFS2_COMPR_NONE; 521da177e4SLinus Torvalds int compr_ret; 531da177e4SLinus Torvalds struct jffs2_compressor *this, *best=NULL; 541da177e4SLinus Torvalds unsigned char *output_buf = NULL, *tmp_buf; 551da177e4SLinus Torvalds uint32_t orig_slen, orig_dlen; 561da177e4SLinus Torvalds uint32_t best_slen=0, best_dlen=0; 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds switch (jffs2_compression_mode) { 591da177e4SLinus Torvalds case JFFS2_COMPR_MODE_NONE: 601da177e4SLinus Torvalds break; 611da177e4SLinus Torvalds case JFFS2_COMPR_MODE_PRIORITY: 621da177e4SLinus Torvalds output_buf = kmalloc(*cdatalen,GFP_KERNEL); 631da177e4SLinus Torvalds if (!output_buf) { 641da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n"); 651da177e4SLinus Torvalds goto out; 661da177e4SLinus Torvalds } 671da177e4SLinus Torvalds orig_slen = *datalen; 681da177e4SLinus Torvalds orig_dlen = *cdatalen; 691da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 701da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 711da177e4SLinus Torvalds /* Skip decompress-only backwards-compatibility and disabled modules */ 721da177e4SLinus Torvalds if ((!this->compress)||(this->disabled)) 731da177e4SLinus Torvalds continue; 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds this->usecount++; 761da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 771da177e4SLinus Torvalds *datalen = orig_slen; 781da177e4SLinus Torvalds *cdatalen = orig_dlen; 791da177e4SLinus Torvalds compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL); 801da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 811da177e4SLinus Torvalds this->usecount--; 821da177e4SLinus Torvalds if (!compr_ret) { 831da177e4SLinus Torvalds ret = this->compr; 841da177e4SLinus Torvalds this->stat_compr_blocks++; 851da177e4SLinus Torvalds this->stat_compr_orig_size += *datalen; 861da177e4SLinus Torvalds this->stat_compr_new_size += *cdatalen; 871da177e4SLinus Torvalds break; 881da177e4SLinus Torvalds } 891da177e4SLinus Torvalds } 901da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 911da177e4SLinus Torvalds if (ret == JFFS2_COMPR_NONE) kfree(output_buf); 921da177e4SLinus Torvalds break; 931da177e4SLinus Torvalds case JFFS2_COMPR_MODE_SIZE: 941da177e4SLinus Torvalds orig_slen = *datalen; 951da177e4SLinus Torvalds orig_dlen = *cdatalen; 961da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 971da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 981da177e4SLinus Torvalds /* Skip decompress-only backwards-compatibility and disabled modules */ 991da177e4SLinus Torvalds if ((!this->compress)||(this->disabled)) 1001da177e4SLinus Torvalds continue; 1011da177e4SLinus Torvalds /* Allocating memory for output buffer if necessary */ 1021da177e4SLinus Torvalds if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) { 1031da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1041da177e4SLinus Torvalds kfree(this->compr_buf); 1051da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1061da177e4SLinus Torvalds this->compr_buf_size=0; 1071da177e4SLinus Torvalds this->compr_buf=NULL; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds if (!this->compr_buf) { 1101da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1111da177e4SLinus Torvalds tmp_buf = kmalloc(orig_dlen,GFP_KERNEL); 1121da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1131da177e4SLinus Torvalds if (!tmp_buf) { 1141da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen); 1151da177e4SLinus Torvalds continue; 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds else { 1181da177e4SLinus Torvalds this->compr_buf = tmp_buf; 1191da177e4SLinus Torvalds this->compr_buf_size = orig_dlen; 1201da177e4SLinus Torvalds } 1211da177e4SLinus Torvalds } 1221da177e4SLinus Torvalds this->usecount++; 1231da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1241da177e4SLinus Torvalds *datalen = orig_slen; 1251da177e4SLinus Torvalds *cdatalen = orig_dlen; 1261da177e4SLinus Torvalds compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL); 1271da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1281da177e4SLinus Torvalds this->usecount--; 1291da177e4SLinus Torvalds if (!compr_ret) { 1301da177e4SLinus Torvalds if ((!best_dlen)||(best_dlen>*cdatalen)) { 1311da177e4SLinus Torvalds best_dlen = *cdatalen; 1321da177e4SLinus Torvalds best_slen = *datalen; 1331da177e4SLinus Torvalds best = this; 1341da177e4SLinus Torvalds } 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds } 1371da177e4SLinus Torvalds if (best_dlen) { 1381da177e4SLinus Torvalds *cdatalen = best_dlen; 1391da177e4SLinus Torvalds *datalen = best_slen; 1401da177e4SLinus Torvalds output_buf = best->compr_buf; 1411da177e4SLinus Torvalds best->compr_buf = NULL; 1421da177e4SLinus Torvalds best->compr_buf_size = 0; 1431da177e4SLinus Torvalds best->stat_compr_blocks++; 1441da177e4SLinus Torvalds best->stat_compr_orig_size += best_slen; 1451da177e4SLinus Torvalds best->stat_compr_new_size += best_dlen; 1461da177e4SLinus Torvalds ret = best->compr; 1471da177e4SLinus Torvalds } 1481da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1491da177e4SLinus Torvalds break; 1501da177e4SLinus Torvalds default: 1511da177e4SLinus Torvalds printk(KERN_ERR "JFFS2: unknow compression mode.\n"); 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds out: 1541da177e4SLinus Torvalds if (ret == JFFS2_COMPR_NONE) { 1551da177e4SLinus Torvalds *cpage_out = data_in; 1561da177e4SLinus Torvalds *datalen = *cdatalen; 1571da177e4SLinus Torvalds none_stat_compr_blocks++; 1581da177e4SLinus Torvalds none_stat_compr_size += *datalen; 1591da177e4SLinus Torvalds } 1601da177e4SLinus Torvalds else { 1611da177e4SLinus Torvalds *cpage_out = output_buf; 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds return ret; 1641da177e4SLinus Torvalds } 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 1671da177e4SLinus Torvalds uint16_t comprtype, unsigned char *cdata_in, 1681da177e4SLinus Torvalds unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) 1691da177e4SLinus Torvalds { 1701da177e4SLinus Torvalds struct jffs2_compressor *this; 1711da177e4SLinus Torvalds int ret; 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds /* Older code had a bug where it would write non-zero 'usercompr' 1741da177e4SLinus Torvalds fields. Deal with it. */ 1751da177e4SLinus Torvalds if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB) 1761da177e4SLinus Torvalds comprtype &= 0xff; 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds switch (comprtype & 0xff) { 1791da177e4SLinus Torvalds case JFFS2_COMPR_NONE: 1801da177e4SLinus Torvalds /* This should be special-cased elsewhere, but we might as well deal with it */ 1811da177e4SLinus Torvalds memcpy(data_out, cdata_in, datalen); 1821da177e4SLinus Torvalds none_stat_decompr_blocks++; 1831da177e4SLinus Torvalds break; 1841da177e4SLinus Torvalds case JFFS2_COMPR_ZERO: 1851da177e4SLinus Torvalds memset(data_out, 0, datalen); 1861da177e4SLinus Torvalds break; 1871da177e4SLinus Torvalds default: 1881da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1891da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 1901da177e4SLinus Torvalds if (comprtype == this->compr) { 1911da177e4SLinus Torvalds this->usecount++; 1921da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1931da177e4SLinus Torvalds ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL); 1941da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1951da177e4SLinus Torvalds if (ret) { 1961da177e4SLinus Torvalds printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); 1971da177e4SLinus Torvalds } 1981da177e4SLinus Torvalds else { 1991da177e4SLinus Torvalds this->stat_decompr_blocks++; 2001da177e4SLinus Torvalds } 2011da177e4SLinus Torvalds this->usecount--; 2021da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2031da177e4SLinus Torvalds return ret; 2041da177e4SLinus Torvalds } 2051da177e4SLinus Torvalds } 2061da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype); 2071da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2081da177e4SLinus Torvalds return -EIO; 2091da177e4SLinus Torvalds } 2101da177e4SLinus Torvalds return 0; 2111da177e4SLinus Torvalds } 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds int jffs2_register_compressor(struct jffs2_compressor *comp) 2141da177e4SLinus Torvalds { 2151da177e4SLinus Torvalds struct jffs2_compressor *this; 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds if (!comp->name) { 2181da177e4SLinus Torvalds printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n"); 2191da177e4SLinus Torvalds return -1; 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds comp->compr_buf_size=0; 2221da177e4SLinus Torvalds comp->compr_buf=NULL; 2231da177e4SLinus Torvalds comp->usecount=0; 2241da177e4SLinus Torvalds comp->stat_compr_orig_size=0; 2251da177e4SLinus Torvalds comp->stat_compr_new_size=0; 2261da177e4SLinus Torvalds comp->stat_compr_blocks=0; 2271da177e4SLinus Torvalds comp->stat_decompr_blocks=0; 2281da177e4SLinus Torvalds D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name)); 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 2331da177e4SLinus Torvalds if (this->priority < comp->priority) { 2341da177e4SLinus Torvalds list_add(&comp->list, this->list.prev); 2351da177e4SLinus Torvalds goto out; 2361da177e4SLinus Torvalds } 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds list_add_tail(&comp->list, &jffs2_compressor_list); 2391da177e4SLinus Torvalds out: 2401da177e4SLinus Torvalds D2(list_for_each_entry(this, &jffs2_compressor_list, list) { 2411da177e4SLinus Torvalds printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); 2421da177e4SLinus Torvalds }) 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds return 0; 2471da177e4SLinus Torvalds } 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds int jffs2_unregister_compressor(struct jffs2_compressor *comp) 2501da177e4SLinus Torvalds { 2511da177e4SLinus Torvalds D2(struct jffs2_compressor *this;) 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name)); 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds if (comp->usecount) { 2581da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2591da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n"); 2601da177e4SLinus Torvalds return -1; 2611da177e4SLinus Torvalds } 2621da177e4SLinus Torvalds list_del(&comp->list); 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds D2(list_for_each_entry(this, &jffs2_compressor_list, list) { 2651da177e4SLinus Torvalds printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); 2661da177e4SLinus Torvalds }) 2671da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2681da177e4SLinus Torvalds return 0; 2691da177e4SLinus Torvalds } 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_PROC 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds #define JFFS2_STAT_BUF_SIZE 16000 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds char *jffs2_list_compressors(void) 2761da177e4SLinus Torvalds { 2771da177e4SLinus Torvalds struct jffs2_compressor *this; 2781da177e4SLinus Torvalds char *buf, *act_buf; 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); 2811da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 2821da177e4SLinus Torvalds act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority); 2831da177e4SLinus Torvalds if ((this->disabled)||(!this->compress)) 2841da177e4SLinus Torvalds act_buf += sprintf(act_buf,"disabled"); 2851da177e4SLinus Torvalds else 2861da177e4SLinus Torvalds act_buf += sprintf(act_buf,"enabled"); 2871da177e4SLinus Torvalds act_buf += sprintf(act_buf,"\n"); 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds return buf; 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds char *jffs2_stats(void) 2931da177e4SLinus Torvalds { 2941da177e4SLinus Torvalds struct jffs2_compressor *this; 2951da177e4SLinus Torvalds char *buf, *act_buf; 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); 2981da177e4SLinus Torvalds 2991da177e4SLinus Torvalds act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n"); 3001da177e4SLinus Torvalds act_buf += sprintf(act_buf,"%10s ","none"); 3011da177e4SLinus Torvalds act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, 3021da177e4SLinus Torvalds none_stat_compr_size, none_stat_decompr_blocks); 3031da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 3041da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 3051da177e4SLinus Torvalds act_buf += sprintf(act_buf,"%10s ",this->name); 3061da177e4SLinus Torvalds if ((this->disabled)||(!this->compress)) 3071da177e4SLinus Torvalds act_buf += sprintf(act_buf,"- "); 3081da177e4SLinus Torvalds else 3091da177e4SLinus Torvalds act_buf += sprintf(act_buf,"+ "); 3101da177e4SLinus Torvalds act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, 3111da177e4SLinus Torvalds this->stat_compr_new_size, this->stat_compr_orig_size, 3121da177e4SLinus Torvalds this->stat_decompr_blocks); 3131da177e4SLinus Torvalds act_buf += sprintf(act_buf,"\n"); 3141da177e4SLinus Torvalds } 3151da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds return buf; 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds 3201da177e4SLinus Torvalds char *jffs2_get_compression_mode_name(void) 3211da177e4SLinus Torvalds { 3221da177e4SLinus Torvalds switch (jffs2_compression_mode) { 3231da177e4SLinus Torvalds case JFFS2_COMPR_MODE_NONE: 3241da177e4SLinus Torvalds return "none"; 3251da177e4SLinus Torvalds case JFFS2_COMPR_MODE_PRIORITY: 3261da177e4SLinus Torvalds return "priority"; 3271da177e4SLinus Torvalds case JFFS2_COMPR_MODE_SIZE: 3281da177e4SLinus Torvalds return "size"; 3291da177e4SLinus Torvalds } 3301da177e4SLinus Torvalds return "unkown"; 3311da177e4SLinus Torvalds } 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds int jffs2_set_compression_mode_name(const char *name) 3341da177e4SLinus Torvalds { 3351da177e4SLinus Torvalds if (!strcmp("none",name)) { 3361da177e4SLinus Torvalds jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; 3371da177e4SLinus Torvalds return 0; 3381da177e4SLinus Torvalds } 3391da177e4SLinus Torvalds if (!strcmp("priority",name)) { 3401da177e4SLinus Torvalds jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; 3411da177e4SLinus Torvalds return 0; 3421da177e4SLinus Torvalds } 3431da177e4SLinus Torvalds if (!strcmp("size",name)) { 3441da177e4SLinus Torvalds jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; 3451da177e4SLinus Torvalds return 0; 3461da177e4SLinus Torvalds } 3471da177e4SLinus Torvalds return 1; 3481da177e4SLinus Torvalds } 3491da177e4SLinus Torvalds 3501da177e4SLinus Torvalds static int jffs2_compressor_Xable(const char *name, int disabled) 3511da177e4SLinus Torvalds { 3521da177e4SLinus Torvalds struct jffs2_compressor *this; 3531da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 3541da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 3551da177e4SLinus Torvalds if (!strcmp(this->name, name)) { 3561da177e4SLinus Torvalds this->disabled = disabled; 3571da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 3581da177e4SLinus Torvalds return 0; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds } 3611da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 3621da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); 3631da177e4SLinus Torvalds return 1; 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds 3661da177e4SLinus Torvalds int jffs2_enable_compressor_name(const char *name) 3671da177e4SLinus Torvalds { 3681da177e4SLinus Torvalds return jffs2_compressor_Xable(name, 0); 3691da177e4SLinus Torvalds } 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds int jffs2_disable_compressor_name(const char *name) 3721da177e4SLinus Torvalds { 3731da177e4SLinus Torvalds return jffs2_compressor_Xable(name, 1); 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds int jffs2_set_compressor_priority(const char *name, int priority) 3771da177e4SLinus Torvalds { 3781da177e4SLinus Torvalds struct jffs2_compressor *this,*comp; 3791da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 3801da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 3811da177e4SLinus Torvalds if (!strcmp(this->name, name)) { 3821da177e4SLinus Torvalds this->priority = priority; 3831da177e4SLinus Torvalds comp = this; 3841da177e4SLinus Torvalds goto reinsert; 3851da177e4SLinus Torvalds } 3861da177e4SLinus Torvalds } 3871da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 3881da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); 3891da177e4SLinus Torvalds return 1; 3901da177e4SLinus Torvalds reinsert: 3911da177e4SLinus Torvalds /* list is sorted in the order of priority, so if 3921da177e4SLinus Torvalds we change it we have to reinsert it into the 3931da177e4SLinus Torvalds good place */ 3941da177e4SLinus Torvalds list_del(&comp->list); 3951da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 3961da177e4SLinus Torvalds if (this->priority < comp->priority) { 3971da177e4SLinus Torvalds list_add(&comp->list, this->list.prev); 3981da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 3991da177e4SLinus Torvalds return 0; 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds } 4021da177e4SLinus Torvalds list_add_tail(&comp->list, &jffs2_compressor_list); 4031da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 4041da177e4SLinus Torvalds return 0; 4051da177e4SLinus Torvalds } 4061da177e4SLinus Torvalds 4071da177e4SLinus Torvalds #endif 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) 4101da177e4SLinus Torvalds { 4111da177e4SLinus Torvalds if (orig != comprbuf) 4121da177e4SLinus Torvalds kfree(comprbuf); 4131da177e4SLinus Torvalds } 4141da177e4SLinus Torvalds 4157d2beb13SDavid Brownell int __init jffs2_compressors_init(void) 4161da177e4SLinus Torvalds { 4171da177e4SLinus Torvalds /* Registering compressors */ 4181da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_ZLIB 4191da177e4SLinus Torvalds jffs2_zlib_init(); 4201da177e4SLinus Torvalds #endif 4211da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_RTIME 4221da177e4SLinus Torvalds jffs2_rtime_init(); 4231da177e4SLinus Torvalds #endif 4241da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_RUBIN 4251da177e4SLinus Torvalds jffs2_rubinmips_init(); 4261da177e4SLinus Torvalds jffs2_dynrubin_init(); 4271da177e4SLinus Torvalds #endif 4281da177e4SLinus Torvalds /* Setting default compression mode */ 4291da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_CMODE_NONE 4301da177e4SLinus Torvalds jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; 4311da177e4SLinus Torvalds D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");) 4321da177e4SLinus Torvalds #else 4331da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_CMODE_SIZE 4341da177e4SLinus Torvalds jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; 4351da177e4SLinus Torvalds D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");) 4361da177e4SLinus Torvalds #else 4371da177e4SLinus Torvalds D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");) 4381da177e4SLinus Torvalds #endif 4391da177e4SLinus Torvalds #endif 4401da177e4SLinus Torvalds return 0; 4411da177e4SLinus Torvalds } 4421da177e4SLinus Torvalds 4433bcc86f5SDavid Woodhouse int jffs2_compressors_exit(void) 4441da177e4SLinus Torvalds { 4451da177e4SLinus Torvalds /* Unregistering compressors */ 4461da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_RUBIN 4471da177e4SLinus Torvalds jffs2_dynrubin_exit(); 4481da177e4SLinus Torvalds jffs2_rubinmips_exit(); 4491da177e4SLinus Torvalds #endif 4501da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_RTIME 4511da177e4SLinus Torvalds jffs2_rtime_exit(); 4521da177e4SLinus Torvalds #endif 4531da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_ZLIB 4541da177e4SLinus Torvalds jffs2_zlib_exit(); 4551da177e4SLinus Torvalds #endif 4561da177e4SLinus Torvalds return 0; 4571da177e4SLinus Torvalds } 458