0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
0022 static LIST_HEAD(jffs2_compressor_list);
0023
0024
0025 static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
0026
0027
0028 static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
0029
0030
0031
0032
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
0055 return 0;
0056 }
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
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
0092 if (!this->compress || this->disabled)
0093 continue;
0094
0095
0096 if (compr && (compr != this->compr))
0097 continue;
0098
0099
0100
0101
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
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
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
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
0178 if ((!this->compress)||(this->disabled))
0179 continue;
0180
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
0261
0262 if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB)
0263 comprtype &= 0xff;
0264
0265 switch (comprtype & 0xff) {
0266 case JFFS2_COMPR_NONE:
0267
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
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
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
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 }