diff --git a/fs/Kconfig b/fs/Kconfig index a2ec0b375dff34ca29d5581699876f2ad2c1772a..42cfb7dc95b5d8d48e25a07bf6d2b5d342e8a953 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1364,6 +1364,13 @@ config JFFS2_CMODE_SIZE Tries all compressors and chooses the one which has the smallest result. +config JFFS2_CMODE_FAVOURLZO + bool "Favour LZO" + help + Tries all compressors and chooses the one which has the smallest + result but gives some preference to LZO (which has faster + decompression) at the expense of size. + endchoice config CRAMFS diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index bcc28d266a122380bf66fd3484d47ccad53d4d03..86739ee53b37336c15cbc341180c47d195d9081a 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -24,6 +24,34 @@ static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; /* Statistics for blocks stored without compression */ static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0; + +/* + * Return 1 to use this compression + */ +static int jffs2_is_best_compression(struct jffs2_compressor *this, + struct jffs2_compressor *best, uint32_t size, uint32_t bestsize) +{ + switch (jffs2_compression_mode) { + case JFFS2_COMPR_MODE_SIZE: + if (bestsize > size) + return 1; + return 0; + case JFFS2_COMPR_MODE_FAVOURLZO: + if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size)) + return 1; + if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size)) + return 1; + if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100))) + return 1; + if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size) + return 1; + + return 0; + } + /* Shouldn't happen */ + return 0; +} + /* jffs2_compress: * @data: Pointer to uncompressed data * @cdata: Pointer to returned pointer to buffer for compressed data @@ -90,6 +118,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, kfree(output_buf); break; case JFFS2_COMPR_MODE_SIZE: + case JFFS2_COMPR_MODE_FAVOURLZO: orig_slen = *datalen; orig_dlen = *cdatalen; spin_lock(&jffs2_compressor_list_lock); @@ -98,7 +127,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, if ((!this->compress)||(this->disabled)) continue; /* Allocating memory for output buffer if necessary */ - if ((this->compr_buf_sizecompr_buf)) { + if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) { spin_unlock(&jffs2_compressor_list_lock); kfree(this->compr_buf); spin_lock(&jffs2_compressor_list_lock); @@ -107,15 +136,15 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } if (!this->compr_buf) { spin_unlock(&jffs2_compressor_list_lock); - tmp_buf = kmalloc(orig_dlen,GFP_KERNEL); + tmp_buf = kmalloc(orig_slen, GFP_KERNEL); spin_lock(&jffs2_compressor_list_lock); if (!tmp_buf) { - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen); + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n", orig_slen); continue; } else { this->compr_buf = tmp_buf; - this->compr_buf_size = orig_dlen; + this->compr_buf_size = orig_slen; } } this->usecount++; @@ -126,7 +155,8 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, spin_lock(&jffs2_compressor_list_lock); this->usecount--; if (!compr_ret) { - if ((!best_dlen)||(best_dlen>*cdatalen)) { + if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen)) + && (*cdatalen < *datalen)) { best_dlen = *cdatalen; best_slen = *datalen; best = this; @@ -297,9 +327,14 @@ int __init jffs2_compressors_init(void) #ifdef CONFIG_JFFS2_CMODE_SIZE jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");) +#else +#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO + jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO; + D1(printk(KERN_INFO "JFFS2: default compression mode: favourlzo\n");) #else D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");) #endif +#endif #endif return 0; } diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index a54828a4e9c6cafff75f455c6f843fd1a1e0e609..e1b7efb70aa4951322f60582df08ce6687f1f6a6 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -38,6 +38,9 @@ #define JFFS2_COMPR_MODE_NONE 0 #define JFFS2_COMPR_MODE_PRIORITY 1 #define JFFS2_COMPR_MODE_SIZE 2 +#define JFFS2_COMPR_MODE_FAVOURLZO 3 + +#define FAVOUR_LZO_PERCENT 80 struct jffs2_compressor { struct list_head list;