11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * JFFS2 -- Journalling Flash File System, Version 2. 31da177e4SLinus Torvalds * 4c00c310eSDavid Woodhouse * Copyright © 2001-2007 Red Hat, Inc. 51da177e4SLinus Torvalds * Created by Arjan van de Ven <arjanv@redhat.com> 61da177e4SLinus Torvalds * 7c00c310eSDavid Woodhouse * Copyright © 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 * 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include "compr.h" 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds static DEFINE_SPINLOCK(jffs2_compressor_list_lock); 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds /* Available compressors are on this list */ 191da177e4SLinus Torvalds static LIST_HEAD(jffs2_compressor_list); 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds /* Actual compression mode */ 221da177e4SLinus Torvalds static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds /* Statistics for blocks stored without compression */ 251da177e4SLinus Torvalds static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0; 261da177e4SLinus Torvalds 273b23c1f5SRichard Purdie 283b23c1f5SRichard Purdie /* 293b23c1f5SRichard Purdie * Return 1 to use this compression 303b23c1f5SRichard Purdie */ 313b23c1f5SRichard Purdie static int jffs2_is_best_compression(struct jffs2_compressor *this, 323b23c1f5SRichard Purdie struct jffs2_compressor *best, uint32_t size, uint32_t bestsize) 333b23c1f5SRichard Purdie { 343b23c1f5SRichard Purdie switch (jffs2_compression_mode) { 353b23c1f5SRichard Purdie case JFFS2_COMPR_MODE_SIZE: 363b23c1f5SRichard Purdie if (bestsize > size) 373b23c1f5SRichard Purdie return 1; 383b23c1f5SRichard Purdie return 0; 393b23c1f5SRichard Purdie case JFFS2_COMPR_MODE_FAVOURLZO: 403b23c1f5SRichard Purdie if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size)) 413b23c1f5SRichard Purdie return 1; 423b23c1f5SRichard Purdie if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size)) 433b23c1f5SRichard Purdie return 1; 443b23c1f5SRichard Purdie if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100))) 453b23c1f5SRichard Purdie return 1; 463b23c1f5SRichard Purdie if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size) 473b23c1f5SRichard Purdie return 1; 483b23c1f5SRichard Purdie 493b23c1f5SRichard Purdie return 0; 503b23c1f5SRichard Purdie } 513b23c1f5SRichard Purdie /* Shouldn't happen */ 523b23c1f5SRichard Purdie return 0; 533b23c1f5SRichard Purdie } 543b23c1f5SRichard Purdie 551da177e4SLinus Torvalds /* jffs2_compress: 56faa5c2a1SGeert Uytterhoeven * @data_in: Pointer to uncompressed data 57faa5c2a1SGeert Uytterhoeven * @cpage_out: Pointer to returned pointer to buffer for compressed data 581da177e4SLinus Torvalds * @datalen: On entry, holds the amount of data available for compression. 591da177e4SLinus Torvalds * On exit, expected to hold the amount of data actually compressed. 601da177e4SLinus Torvalds * @cdatalen: On entry, holds the amount of space available for compressed 611da177e4SLinus Torvalds * data. On exit, expected to hold the actual size of the compressed 621da177e4SLinus Torvalds * data. 631da177e4SLinus Torvalds * 641da177e4SLinus Torvalds * Returns: Lower byte to be stored with data indicating compression type used. 651da177e4SLinus Torvalds * Zero is used to show that the data could not be compressed - the 661da177e4SLinus Torvalds * compressed version was actually larger than the original. 671da177e4SLinus Torvalds * Upper byte will be used later. (soon) 681da177e4SLinus Torvalds * 691da177e4SLinus Torvalds * If the cdata buffer isn't large enough to hold all the uncompressed data, 701da177e4SLinus Torvalds * jffs2_compress should compress as much as will fit, and should set 711da177e4SLinus Torvalds * *datalen accordingly to show the amount of data which were compressed. 721da177e4SLinus Torvalds */ 731da177e4SLinus Torvalds uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 741da177e4SLinus Torvalds unsigned char *data_in, unsigned char **cpage_out, 751da177e4SLinus Torvalds uint32_t *datalen, uint32_t *cdatalen) 761da177e4SLinus Torvalds { 771da177e4SLinus Torvalds int ret = JFFS2_COMPR_NONE; 781da177e4SLinus Torvalds int compr_ret; 791da177e4SLinus Torvalds struct jffs2_compressor *this, *best=NULL; 801da177e4SLinus Torvalds unsigned char *output_buf = NULL, *tmp_buf; 811da177e4SLinus Torvalds uint32_t orig_slen, orig_dlen; 821da177e4SLinus Torvalds uint32_t best_slen=0, best_dlen=0; 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds switch (jffs2_compression_mode) { 851da177e4SLinus Torvalds case JFFS2_COMPR_MODE_NONE: 861da177e4SLinus Torvalds break; 871da177e4SLinus Torvalds case JFFS2_COMPR_MODE_PRIORITY: 881da177e4SLinus Torvalds output_buf = kmalloc(*cdatalen,GFP_KERNEL); 891da177e4SLinus Torvalds if (!output_buf) { 901da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n"); 911da177e4SLinus Torvalds goto out; 921da177e4SLinus Torvalds } 931da177e4SLinus Torvalds orig_slen = *datalen; 941da177e4SLinus Torvalds orig_dlen = *cdatalen; 951da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 961da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 971da177e4SLinus Torvalds /* Skip decompress-only backwards-compatibility and disabled modules */ 981da177e4SLinus Torvalds if ((!this->compress)||(this->disabled)) 991da177e4SLinus Torvalds continue; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds this->usecount++; 1021da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1031da177e4SLinus Torvalds *datalen = orig_slen; 1041da177e4SLinus Torvalds *cdatalen = orig_dlen; 1051da177e4SLinus Torvalds compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL); 1061da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1071da177e4SLinus Torvalds this->usecount--; 1081da177e4SLinus Torvalds if (!compr_ret) { 1091da177e4SLinus Torvalds ret = this->compr; 1101da177e4SLinus Torvalds this->stat_compr_blocks++; 1111da177e4SLinus Torvalds this->stat_compr_orig_size += *datalen; 1121da177e4SLinus Torvalds this->stat_compr_new_size += *cdatalen; 1131da177e4SLinus Torvalds break; 1141da177e4SLinus Torvalds } 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 117ef53cb02SDavid Woodhouse if (ret == JFFS2_COMPR_NONE) 118ef53cb02SDavid Woodhouse kfree(output_buf); 1191da177e4SLinus Torvalds break; 1201da177e4SLinus Torvalds case JFFS2_COMPR_MODE_SIZE: 1213b23c1f5SRichard Purdie case JFFS2_COMPR_MODE_FAVOURLZO: 1221da177e4SLinus Torvalds orig_slen = *datalen; 1231da177e4SLinus Torvalds orig_dlen = *cdatalen; 1241da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1251da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 1261da177e4SLinus Torvalds /* Skip decompress-only backwards-compatibility and disabled modules */ 1271da177e4SLinus Torvalds if ((!this->compress)||(this->disabled)) 1281da177e4SLinus Torvalds continue; 1291da177e4SLinus Torvalds /* Allocating memory for output buffer if necessary */ 1303b23c1f5SRichard Purdie if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) { 1311da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1321da177e4SLinus Torvalds kfree(this->compr_buf); 1331da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1341da177e4SLinus Torvalds this->compr_buf_size=0; 1351da177e4SLinus Torvalds this->compr_buf=NULL; 1361da177e4SLinus Torvalds } 1371da177e4SLinus Torvalds if (!this->compr_buf) { 1381da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1393b23c1f5SRichard Purdie tmp_buf = kmalloc(orig_slen, GFP_KERNEL); 1401da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1411da177e4SLinus Torvalds if (!tmp_buf) { 1423b23c1f5SRichard Purdie printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n", orig_slen); 1431da177e4SLinus Torvalds continue; 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds else { 1461da177e4SLinus Torvalds this->compr_buf = tmp_buf; 1473b23c1f5SRichard Purdie this->compr_buf_size = orig_slen; 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds } 1501da177e4SLinus Torvalds this->usecount++; 1511da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1521da177e4SLinus Torvalds *datalen = orig_slen; 1531da177e4SLinus Torvalds *cdatalen = orig_dlen; 1541da177e4SLinus Torvalds compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL); 1551da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 1561da177e4SLinus Torvalds this->usecount--; 1571da177e4SLinus Torvalds if (!compr_ret) { 1583b23c1f5SRichard Purdie if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen)) 1593b23c1f5SRichard Purdie && (*cdatalen < *datalen)) { 1601da177e4SLinus Torvalds best_dlen = *cdatalen; 1611da177e4SLinus Torvalds best_slen = *datalen; 1621da177e4SLinus Torvalds best = this; 1631da177e4SLinus Torvalds } 1641da177e4SLinus Torvalds } 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds if (best_dlen) { 1671da177e4SLinus Torvalds *cdatalen = best_dlen; 1681da177e4SLinus Torvalds *datalen = best_slen; 1691da177e4SLinus Torvalds output_buf = best->compr_buf; 1701da177e4SLinus Torvalds best->compr_buf = NULL; 1711da177e4SLinus Torvalds best->compr_buf_size = 0; 1721da177e4SLinus Torvalds best->stat_compr_blocks++; 1731da177e4SLinus Torvalds best->stat_compr_orig_size += best_slen; 1741da177e4SLinus Torvalds best->stat_compr_new_size += best_dlen; 1751da177e4SLinus Torvalds ret = best->compr; 1761da177e4SLinus Torvalds } 1771da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 1781da177e4SLinus Torvalds break; 1791da177e4SLinus Torvalds default: 1801da177e4SLinus Torvalds printk(KERN_ERR "JFFS2: unknow compression mode.\n"); 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds out: 1831da177e4SLinus Torvalds if (ret == JFFS2_COMPR_NONE) { 1841da177e4SLinus Torvalds *cpage_out = data_in; 1851da177e4SLinus Torvalds *datalen = *cdatalen; 1861da177e4SLinus Torvalds none_stat_compr_blocks++; 1871da177e4SLinus Torvalds none_stat_compr_size += *datalen; 1881da177e4SLinus Torvalds } 1891da177e4SLinus Torvalds else { 1901da177e4SLinus Torvalds *cpage_out = output_buf; 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds return ret; 1931da177e4SLinus Torvalds } 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 1961da177e4SLinus Torvalds uint16_t comprtype, unsigned char *cdata_in, 1971da177e4SLinus Torvalds unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) 1981da177e4SLinus Torvalds { 1991da177e4SLinus Torvalds struct jffs2_compressor *this; 2001da177e4SLinus Torvalds int ret; 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds /* Older code had a bug where it would write non-zero 'usercompr' 2031da177e4SLinus Torvalds fields. Deal with it. */ 2041da177e4SLinus Torvalds if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB) 2051da177e4SLinus Torvalds comprtype &= 0xff; 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds switch (comprtype & 0xff) { 2081da177e4SLinus Torvalds case JFFS2_COMPR_NONE: 2091da177e4SLinus Torvalds /* This should be special-cased elsewhere, but we might as well deal with it */ 2101da177e4SLinus Torvalds memcpy(data_out, cdata_in, datalen); 2111da177e4SLinus Torvalds none_stat_decompr_blocks++; 2121da177e4SLinus Torvalds break; 2131da177e4SLinus Torvalds case JFFS2_COMPR_ZERO: 2141da177e4SLinus Torvalds memset(data_out, 0, datalen); 2151da177e4SLinus Torvalds break; 2161da177e4SLinus Torvalds default: 2171da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 2181da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 2191da177e4SLinus Torvalds if (comprtype == this->compr) { 2201da177e4SLinus Torvalds this->usecount++; 2211da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2221da177e4SLinus Torvalds ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL); 2231da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 2241da177e4SLinus Torvalds if (ret) { 2251da177e4SLinus Torvalds printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds else { 2281da177e4SLinus Torvalds this->stat_decompr_blocks++; 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds this->usecount--; 2311da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2321da177e4SLinus Torvalds return ret; 2331da177e4SLinus Torvalds } 2341da177e4SLinus Torvalds } 2351da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype); 2361da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2371da177e4SLinus Torvalds return -EIO; 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds return 0; 2401da177e4SLinus Torvalds } 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds int jffs2_register_compressor(struct jffs2_compressor *comp) 2431da177e4SLinus Torvalds { 2441da177e4SLinus Torvalds struct jffs2_compressor *this; 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds if (!comp->name) { 2471da177e4SLinus Torvalds printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n"); 2481da177e4SLinus Torvalds return -1; 2491da177e4SLinus Torvalds } 2501da177e4SLinus Torvalds comp->compr_buf_size=0; 2511da177e4SLinus Torvalds comp->compr_buf=NULL; 2521da177e4SLinus Torvalds comp->usecount=0; 2531da177e4SLinus Torvalds comp->stat_compr_orig_size=0; 2541da177e4SLinus Torvalds comp->stat_compr_new_size=0; 2551da177e4SLinus Torvalds comp->stat_compr_blocks=0; 2561da177e4SLinus Torvalds comp->stat_decompr_blocks=0; 2571da177e4SLinus Torvalds D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name)); 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds list_for_each_entry(this, &jffs2_compressor_list, list) { 2621da177e4SLinus Torvalds if (this->priority < comp->priority) { 2631da177e4SLinus Torvalds list_add(&comp->list, this->list.prev); 2641da177e4SLinus Torvalds goto out; 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds } 2671da177e4SLinus Torvalds list_add_tail(&comp->list, &jffs2_compressor_list); 2681da177e4SLinus Torvalds out: 2691da177e4SLinus Torvalds D2(list_for_each_entry(this, &jffs2_compressor_list, list) { 2701da177e4SLinus Torvalds printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); 2711da177e4SLinus Torvalds }) 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds return 0; 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds int jffs2_unregister_compressor(struct jffs2_compressor *comp) 2791da177e4SLinus Torvalds { 2801da177e4SLinus Torvalds D2(struct jffs2_compressor *this;) 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name)); 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds spin_lock(&jffs2_compressor_list_lock); 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds if (comp->usecount) { 2871da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2881da177e4SLinus Torvalds printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n"); 2891da177e4SLinus Torvalds return -1; 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds list_del(&comp->list); 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds D2(list_for_each_entry(this, &jffs2_compressor_list, list) { 2941da177e4SLinus Torvalds printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); 2951da177e4SLinus Torvalds }) 2961da177e4SLinus Torvalds spin_unlock(&jffs2_compressor_list_lock); 2971da177e4SLinus Torvalds return 0; 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) 3011da177e4SLinus Torvalds { 3021da177e4SLinus Torvalds if (orig != comprbuf) 3031da177e4SLinus Torvalds kfree(comprbuf); 3041da177e4SLinus Torvalds } 3051da177e4SLinus Torvalds 3067d2beb13SDavid Brownell int __init jffs2_compressors_init(void) 3071da177e4SLinus Torvalds { 3081da177e4SLinus Torvalds /* Registering compressors */ 3091da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_ZLIB 3101da177e4SLinus Torvalds jffs2_zlib_init(); 3111da177e4SLinus Torvalds #endif 3121da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_RTIME 3131da177e4SLinus Torvalds jffs2_rtime_init(); 3141da177e4SLinus Torvalds #endif 3151da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_RUBIN 3161da177e4SLinus Torvalds jffs2_rubinmips_init(); 3171da177e4SLinus Torvalds jffs2_dynrubin_init(); 3181da177e4SLinus Torvalds #endif 319c799aca3SRichard Purdie #ifdef CONFIG_JFFS2_LZO 320c799aca3SRichard Purdie jffs2_lzo_init(); 321c799aca3SRichard Purdie #endif 3221da177e4SLinus Torvalds /* Setting default compression mode */ 3231da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_CMODE_NONE 3241da177e4SLinus Torvalds jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; 3251da177e4SLinus Torvalds D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");) 3261da177e4SLinus Torvalds #else 3271da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_CMODE_SIZE 3281da177e4SLinus Torvalds jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; 3291da177e4SLinus Torvalds D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");) 3301da177e4SLinus Torvalds #else 3313b23c1f5SRichard Purdie #ifdef CONFIG_JFFS2_CMODE_FAVOURLZO 3323b23c1f5SRichard Purdie jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO; 3333b23c1f5SRichard Purdie D1(printk(KERN_INFO "JFFS2: default compression mode: favourlzo\n");) 3343b23c1f5SRichard Purdie #else 3351da177e4SLinus Torvalds D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");) 3361da177e4SLinus Torvalds #endif 3371da177e4SLinus Torvalds #endif 3383b23c1f5SRichard Purdie #endif 3391da177e4SLinus Torvalds return 0; 3401da177e4SLinus Torvalds } 3411da177e4SLinus Torvalds 3423bcc86f5SDavid Woodhouse int jffs2_compressors_exit(void) 3431da177e4SLinus Torvalds { 3441da177e4SLinus Torvalds /* Unregistering compressors */ 345c799aca3SRichard Purdie #ifdef CONFIG_JFFS2_LZO 346c799aca3SRichard Purdie jffs2_lzo_exit(); 347c799aca3SRichard Purdie #endif 3481da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_RUBIN 3491da177e4SLinus Torvalds jffs2_dynrubin_exit(); 3501da177e4SLinus Torvalds jffs2_rubinmips_exit(); 3511da177e4SLinus Torvalds #endif 3521da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_RTIME 3531da177e4SLinus Torvalds jffs2_rtime_exit(); 3541da177e4SLinus Torvalds #endif 3551da177e4SLinus Torvalds #ifdef CONFIG_JFFS2_ZLIB 3561da177e4SLinus Torvalds jffs2_zlib_exit(); 3571da177e4SLinus Torvalds #endif 3581da177e4SLinus Torvalds return 0; 3591da177e4SLinus Torvalds } 360