Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * JFFS2 -- Journalling Flash File System, Version 2.
0003  *
0004  * Copyright © 2001-2007 Red Hat, Inc.
0005  * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
0006  * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
0007  *          University of Szeged, Hungary
0008  *
0009  * Created by Arjan van de Ven <arjan@infradead.org>
0010  *
0011  * For licensing information, see the file 'LICENCE' in this directory.
0012  *
0013  */
0014 
0015 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0016 
0017 #include "compr.h"
0018 
0019 static DEFINE_SPINLOCK(jffs2_compressor_list_lock);
0020 
0021 /* Available compressors are on this list */
0022 static LIST_HEAD(jffs2_compressor_list);
0023 
0024 /* Actual compression mode */
0025 static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
0026 
0027 /* Statistics for blocks stored without compression */
0028 static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
0029 
0030 
0031 /*
0032  * Return 1 to use this compression
0033  */
0034 static int jffs2_is_best_compression(struct jffs2_compressor *this,
0035         struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
0036 {
0037     switch (jffs2_compression_mode) {
0038     case JFFS2_COMPR_MODE_SIZE:
0039         if (bestsize > size)
0040             return 1;
0041         return 0;
0042     case JFFS2_COMPR_MODE_FAVOURLZO:
0043         if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
0044             return 1;
0045         if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
0046             return 1;
0047         if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
0048             return 1;
0049         if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
0050             return 1;
0051 
0052         return 0;
0053     }
0054     /* Shouldn't happen */
0055     return 0;
0056 }
0057 
0058 /*
0059  * jffs2_selected_compress:
0060  * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
0061  *  If 0, just take the first available compression mode.
0062  * @data_in: Pointer to uncompressed data
0063  * @cpage_out: Pointer to returned pointer to buffer for compressed data
0064  * @datalen: On entry, holds the amount of data available for compression.
0065  *  On exit, expected to hold the amount of data actually compressed.
0066  * @cdatalen: On entry, holds the amount of space available for compressed
0067  *  data. On exit, expected to hold the actual size of the compressed
0068  *  data.
0069  *
0070  * Returns: the compression type used.  Zero is used to show that the data
0071  * could not be compressed; probably because we couldn't find the requested
0072  * compression mode.
0073  */
0074 static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
0075         unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
0076 {
0077     struct jffs2_compressor *this;
0078     int err, ret = JFFS2_COMPR_NONE;
0079     uint32_t orig_slen, orig_dlen;
0080     char *output_buf;
0081 
0082     output_buf = kmalloc(*cdatalen, GFP_KERNEL);
0083     if (!output_buf) {
0084         pr_warn("No memory for compressor allocation. Compression failed.\n");
0085         return ret;
0086     }
0087     orig_slen = *datalen;
0088     orig_dlen = *cdatalen;
0089     spin_lock(&jffs2_compressor_list_lock);
0090     list_for_each_entry(this, &jffs2_compressor_list, list) {
0091         /* Skip decompress-only and disabled modules */
0092         if (!this->compress || this->disabled)
0093             continue;
0094 
0095         /* Skip if not the desired compression type */
0096         if (compr && (compr != this->compr))
0097             continue;
0098 
0099         /*
0100          * Either compression type was unspecified, or we found our
0101          * compressor; either way, we're good to go.
0102          */
0103         this->usecount++;
0104         spin_unlock(&jffs2_compressor_list_lock);
0105 
0106         *datalen  = orig_slen;
0107         *cdatalen = orig_dlen;
0108         err = this->compress(data_in, output_buf, datalen, cdatalen);
0109 
0110         spin_lock(&jffs2_compressor_list_lock);
0111         this->usecount--;
0112         if (!err) {
0113             /* Success */
0114             ret = this->compr;
0115             this->stat_compr_blocks++;
0116             this->stat_compr_orig_size += *datalen;
0117             this->stat_compr_new_size += *cdatalen;
0118             break;
0119         }
0120     }
0121     spin_unlock(&jffs2_compressor_list_lock);
0122     if (ret == JFFS2_COMPR_NONE)
0123         kfree(output_buf);
0124     else
0125         *cpage_out = output_buf;
0126 
0127     return ret;
0128 }
0129 
0130 /* jffs2_compress:
0131  * @data_in: Pointer to uncompressed data
0132  * @cpage_out: Pointer to returned pointer to buffer for compressed data
0133  * @datalen: On entry, holds the amount of data available for compression.
0134  *  On exit, expected to hold the amount of data actually compressed.
0135  * @cdatalen: On entry, holds the amount of space available for compressed
0136  *  data. On exit, expected to hold the actual size of the compressed
0137  *  data.
0138  *
0139  * Returns: Lower byte to be stored with data indicating compression type used.
0140  * Zero is used to show that the data could not be compressed - the
0141  * compressed version was actually larger than the original.
0142  * Upper byte will be used later. (soon)
0143  *
0144  * If the cdata buffer isn't large enough to hold all the uncompressed data,
0145  * jffs2_compress should compress as much as will fit, and should set
0146  * *datalen accordingly to show the amount of data which were compressed.
0147  */
0148 uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
0149             unsigned char *data_in, unsigned char **cpage_out,
0150             uint32_t *datalen, uint32_t *cdatalen)
0151 {
0152     int ret = JFFS2_COMPR_NONE;
0153     int mode, compr_ret;
0154     struct jffs2_compressor *this, *best=NULL;
0155     unsigned char *output_buf = NULL, *tmp_buf;
0156     uint32_t orig_slen, orig_dlen;
0157     uint32_t best_slen=0, best_dlen=0;
0158 
0159     if (c->mount_opts.override_compr)
0160         mode = c->mount_opts.compr;
0161     else
0162         mode = jffs2_compression_mode;
0163 
0164     switch (mode) {
0165     case JFFS2_COMPR_MODE_NONE:
0166         break;
0167     case JFFS2_COMPR_MODE_PRIORITY:
0168         ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
0169                 cdatalen);
0170         break;
0171     case JFFS2_COMPR_MODE_SIZE:
0172     case JFFS2_COMPR_MODE_FAVOURLZO:
0173         orig_slen = *datalen;
0174         orig_dlen = *cdatalen;
0175         spin_lock(&jffs2_compressor_list_lock);
0176         list_for_each_entry(this, &jffs2_compressor_list, list) {
0177             /* Skip decompress-only backwards-compatibility and disabled modules */
0178             if ((!this->compress)||(this->disabled))
0179                 continue;
0180             /* Allocating memory for output buffer if necessary */
0181             if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
0182                 spin_unlock(&jffs2_compressor_list_lock);
0183                 kfree(this->compr_buf);
0184                 spin_lock(&jffs2_compressor_list_lock);
0185                 this->compr_buf_size=0;
0186                 this->compr_buf=NULL;
0187             }
0188             if (!this->compr_buf) {
0189                 spin_unlock(&jffs2_compressor_list_lock);
0190                 tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
0191                 spin_lock(&jffs2_compressor_list_lock);
0192                 if (!tmp_buf) {
0193                     pr_warn("No memory for compressor allocation. (%d bytes)\n",
0194                         orig_slen);
0195                     continue;
0196                 }
0197                 else {
0198                     this->compr_buf = tmp_buf;
0199                     this->compr_buf_size = orig_slen;
0200                 }
0201             }
0202             this->usecount++;
0203             spin_unlock(&jffs2_compressor_list_lock);
0204             *datalen  = orig_slen;
0205             *cdatalen = orig_dlen;
0206             compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
0207             spin_lock(&jffs2_compressor_list_lock);
0208             this->usecount--;
0209             if (!compr_ret) {
0210                 if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
0211                         && (*cdatalen < *datalen)) {
0212                     best_dlen = *cdatalen;
0213                     best_slen = *datalen;
0214                     best = this;
0215                 }
0216             }
0217         }
0218         if (best_dlen) {
0219             *cdatalen = best_dlen;
0220             *datalen  = best_slen;
0221             output_buf = best->compr_buf;
0222             best->compr_buf = NULL;
0223             best->compr_buf_size = 0;
0224             best->stat_compr_blocks++;
0225             best->stat_compr_orig_size += best_slen;
0226             best->stat_compr_new_size  += best_dlen;
0227             ret = best->compr;
0228             *cpage_out = output_buf;
0229         }
0230         spin_unlock(&jffs2_compressor_list_lock);
0231         break;
0232     case JFFS2_COMPR_MODE_FORCELZO:
0233         ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
0234                 cpage_out, datalen, cdatalen);
0235         break;
0236     case JFFS2_COMPR_MODE_FORCEZLIB:
0237         ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
0238                 cpage_out, datalen, cdatalen);
0239         break;
0240     default:
0241         pr_err("unknown compression mode\n");
0242     }
0243 
0244     if (ret == JFFS2_COMPR_NONE) {
0245         *cpage_out = data_in;
0246         *datalen = *cdatalen;
0247         none_stat_compr_blocks++;
0248         none_stat_compr_size += *datalen;
0249     }
0250     return ret;
0251 }
0252 
0253 int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
0254              uint16_t comprtype, unsigned char *cdata_in,
0255              unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
0256 {
0257     struct jffs2_compressor *this;
0258     int ret;
0259 
0260     /* Older code had a bug where it would write non-zero 'usercompr'
0261        fields. Deal with it. */
0262     if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB)
0263         comprtype &= 0xff;
0264 
0265     switch (comprtype & 0xff) {
0266     case JFFS2_COMPR_NONE:
0267         /* This should be special-cased elsewhere, but we might as well deal with it */
0268         memcpy(data_out, cdata_in, datalen);
0269         none_stat_decompr_blocks++;
0270         break;
0271     case JFFS2_COMPR_ZERO:
0272         memset(data_out, 0, datalen);
0273         break;
0274     default:
0275         spin_lock(&jffs2_compressor_list_lock);
0276         list_for_each_entry(this, &jffs2_compressor_list, list) {
0277             if (comprtype == this->compr) {
0278                 this->usecount++;
0279                 spin_unlock(&jffs2_compressor_list_lock);
0280                 ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
0281                 spin_lock(&jffs2_compressor_list_lock);
0282                 if (ret) {
0283                     pr_warn("Decompressor \"%s\" returned %d\n",
0284                         this->name, ret);
0285                 }
0286                 else {
0287                     this->stat_decompr_blocks++;
0288                 }
0289                 this->usecount--;
0290                 spin_unlock(&jffs2_compressor_list_lock);
0291                 return ret;
0292             }
0293         }
0294         pr_warn("compression type 0x%02x not available\n", comprtype);
0295         spin_unlock(&jffs2_compressor_list_lock);
0296         return -EIO;
0297     }
0298     return 0;
0299 }
0300 
0301 int jffs2_register_compressor(struct jffs2_compressor *comp)
0302 {
0303     struct jffs2_compressor *this;
0304 
0305     if (!comp->name) {
0306         pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n");
0307         return -1;
0308     }
0309     comp->compr_buf_size=0;
0310     comp->compr_buf=NULL;
0311     comp->usecount=0;
0312     comp->stat_compr_orig_size=0;
0313     comp->stat_compr_new_size=0;
0314     comp->stat_compr_blocks=0;
0315     comp->stat_decompr_blocks=0;
0316     jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name);
0317 
0318     spin_lock(&jffs2_compressor_list_lock);
0319 
0320     list_for_each_entry(this, &jffs2_compressor_list, list) {
0321         if (this->priority < comp->priority) {
0322             list_add(&comp->list, this->list.prev);
0323             goto out;
0324         }
0325     }
0326     list_add_tail(&comp->list, &jffs2_compressor_list);
0327 out:
0328     D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
0329         printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
0330     })
0331 
0332     spin_unlock(&jffs2_compressor_list_lock);
0333 
0334     return 0;
0335 }
0336 
0337 int jffs2_unregister_compressor(struct jffs2_compressor *comp)
0338 {
0339     D2(struct jffs2_compressor *this);
0340 
0341     jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name);
0342 
0343     spin_lock(&jffs2_compressor_list_lock);
0344 
0345     if (comp->usecount) {
0346         spin_unlock(&jffs2_compressor_list_lock);
0347         pr_warn("Compressor module is in use. Unregister failed.\n");
0348         return -1;
0349     }
0350     list_del(&comp->list);
0351 
0352     D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
0353         printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
0354     })
0355     spin_unlock(&jffs2_compressor_list_lock);
0356     return 0;
0357 }
0358 
0359 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
0360 {
0361     if (orig != comprbuf)
0362         kfree(comprbuf);
0363 }
0364 
0365 int __init jffs2_compressors_init(void)
0366 {
0367 /* Registering compressors */
0368 #ifdef CONFIG_JFFS2_ZLIB
0369     jffs2_zlib_init();
0370 #endif
0371 #ifdef CONFIG_JFFS2_RTIME
0372     jffs2_rtime_init();
0373 #endif
0374 #ifdef CONFIG_JFFS2_RUBIN
0375     jffs2_rubinmips_init();
0376     jffs2_dynrubin_init();
0377 #endif
0378 #ifdef CONFIG_JFFS2_LZO
0379     jffs2_lzo_init();
0380 #endif
0381 /* Setting default compression mode */
0382 #ifdef CONFIG_JFFS2_CMODE_NONE
0383     jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
0384     jffs2_dbg(1, "default compression mode: none\n");
0385 #else
0386 #ifdef CONFIG_JFFS2_CMODE_SIZE
0387     jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
0388     jffs2_dbg(1, "default compression mode: size\n");
0389 #else
0390 #ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
0391     jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
0392     jffs2_dbg(1, "default compression mode: favourlzo\n");
0393 #else
0394     jffs2_dbg(1, "default compression mode: priority\n");
0395 #endif
0396 #endif
0397 #endif
0398     return 0;
0399 }
0400 
0401 int jffs2_compressors_exit(void)
0402 {
0403 /* Unregistering compressors */
0404 #ifdef CONFIG_JFFS2_LZO
0405     jffs2_lzo_exit();
0406 #endif
0407 #ifdef CONFIG_JFFS2_RUBIN
0408     jffs2_dynrubin_exit();
0409     jffs2_rubinmips_exit();
0410 #endif
0411 #ifdef CONFIG_JFFS2_RTIME
0412     jffs2_rtime_exit();
0413 #endif
0414 #ifdef CONFIG_JFFS2_ZLIB
0415     jffs2_zlib_exit();
0416 #endif
0417     return 0;
0418 }