1 /* 2 * JFFS2 -- Journalling Flash File System, Version 2. 3 * 4 * Copyright © 2001-2007 Red Hat, Inc. 5 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> 6 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 7 * University of Szeged, Hungary 8 * 9 * Created by Arjan van de Ven <arjan@infradead.org> 10 * 11 * For licensing information, see the file 'LICENCE' in this directory. 12 * 13 */ 14 15 #include "compr.h" 16 17 static DEFINE_SPINLOCK(jffs2_compressor_list_lock); 18 19 /* Available compressors are on this list */ 20 static LIST_HEAD(jffs2_compressor_list); 21 22 /* Actual compression mode */ 23 static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; 24 25 /* Statistics for blocks stored without compression */ 26 static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0; 27 28 29 /* 30 * Return 1 to use this compression 31 */ 32 static int jffs2_is_best_compression(struct jffs2_compressor *this, 33 struct jffs2_compressor *best, uint32_t size, uint32_t bestsize) 34 { 35 switch (jffs2_compression_mode) { 36 case JFFS2_COMPR_MODE_SIZE: 37 if (bestsize > size) 38 return 1; 39 return 0; 40 case JFFS2_COMPR_MODE_FAVOURLZO: 41 if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size)) 42 return 1; 43 if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size)) 44 return 1; 45 if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100))) 46 return 1; 47 if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size) 48 return 1; 49 50 return 0; 51 } 52 /* Shouldn't happen */ 53 return 0; 54 } 55 56 /* 57 * jffs2_selected_compress: 58 * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB). 59 * If 0, just take the first available compression mode. 60 * @data_in: Pointer to uncompressed data 61 * @cpage_out: Pointer to returned pointer to buffer for compressed data 62 * @datalen: On entry, holds the amount of data available for compression. 63 * On exit, expected to hold the amount of data actually compressed. 64 * @cdatalen: On entry, holds the amount of space available for compressed 65 * data. On exit, expected to hold the actual size of the compressed 66 * data. 67 * 68 * Returns: the compression type used. Zero is used to show that the data 69 * could not be compressed; probably because we couldn't find the requested 70 * compression mode. 71 */ 72 static int jffs2_selected_compress(u8 compr, unsigned char *data_in, 73 unsigned char **cpage_out, u32 *datalen, u32 *cdatalen) 74 { 75 struct jffs2_compressor *this; 76 int err, ret = JFFS2_COMPR_NONE; 77 uint32_t orig_slen, orig_dlen; 78 char *output_buf; 79 80 output_buf = kmalloc(*cdatalen, GFP_KERNEL); 81 if (!output_buf) { 82 pr_warn("JFFS2: No memory for compressor allocation. Compression failed.\n"); 83 return ret; 84 } 85 orig_slen = *datalen; 86 orig_dlen = *cdatalen; 87 spin_lock(&jffs2_compressor_list_lock); 88 list_for_each_entry(this, &jffs2_compressor_list, list) { 89 /* Skip decompress-only and disabled modules */ 90 if (!this->compress || this->disabled) 91 continue; 92 93 /* Skip if not the desired compression type */ 94 if (compr && (compr != this->compr)) 95 continue; 96 97 /* 98 * Either compression type was unspecified, or we found our 99 * compressor; either way, we're good to go. 100 */ 101 this->usecount++; 102 spin_unlock(&jffs2_compressor_list_lock); 103 104 *datalen = orig_slen; 105 *cdatalen = orig_dlen; 106 err = this->compress(data_in, output_buf, datalen, cdatalen); 107 108 spin_lock(&jffs2_compressor_list_lock); 109 this->usecount--; 110 if (!err) { 111 /* Success */ 112 ret = this->compr; 113 this->stat_compr_blocks++; 114 this->stat_compr_orig_size += *datalen; 115 this->stat_compr_new_size += *cdatalen; 116 break; 117 } 118 } 119 spin_unlock(&jffs2_compressor_list_lock); 120 if (ret == JFFS2_COMPR_NONE) 121 kfree(output_buf); 122 else 123 *cpage_out = output_buf; 124 125 return ret; 126 } 127 128 /* jffs2_compress: 129 * @data_in: Pointer to uncompressed data 130 * @cpage_out: Pointer to returned pointer to buffer for compressed data 131 * @datalen: On entry, holds the amount of data available for compression. 132 * On exit, expected to hold the amount of data actually compressed. 133 * @cdatalen: On entry, holds the amount of space available for compressed 134 * data. On exit, expected to hold the actual size of the compressed 135 * data. 136 * 137 * Returns: Lower byte to be stored with data indicating compression type used. 138 * Zero is used to show that the data could not be compressed - the 139 * compressed version was actually larger than the original. 140 * Upper byte will be used later. (soon) 141 * 142 * If the cdata buffer isn't large enough to hold all the uncompressed data, 143 * jffs2_compress should compress as much as will fit, and should set 144 * *datalen accordingly to show the amount of data which were compressed. 145 */ 146 uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 147 unsigned char *data_in, unsigned char **cpage_out, 148 uint32_t *datalen, uint32_t *cdatalen) 149 { 150 int ret = JFFS2_COMPR_NONE; 151 int mode, compr_ret; 152 struct jffs2_compressor *this, *best=NULL; 153 unsigned char *output_buf = NULL, *tmp_buf; 154 uint32_t orig_slen, orig_dlen; 155 uint32_t best_slen=0, best_dlen=0; 156 157 if (c->mount_opts.override_compr) 158 mode = c->mount_opts.compr; 159 else 160 mode = jffs2_compression_mode; 161 162 switch (mode) { 163 case JFFS2_COMPR_MODE_NONE: 164 break; 165 case JFFS2_COMPR_MODE_PRIORITY: 166 ret = jffs2_selected_compress(0, data_in, cpage_out, datalen, 167 cdatalen); 168 break; 169 case JFFS2_COMPR_MODE_SIZE: 170 case JFFS2_COMPR_MODE_FAVOURLZO: 171 orig_slen = *datalen; 172 orig_dlen = *cdatalen; 173 spin_lock(&jffs2_compressor_list_lock); 174 list_for_each_entry(this, &jffs2_compressor_list, list) { 175 /* Skip decompress-only backwards-compatibility and disabled modules */ 176 if ((!this->compress)||(this->disabled)) 177 continue; 178 /* Allocating memory for output buffer if necessary */ 179 if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) { 180 spin_unlock(&jffs2_compressor_list_lock); 181 kfree(this->compr_buf); 182 spin_lock(&jffs2_compressor_list_lock); 183 this->compr_buf_size=0; 184 this->compr_buf=NULL; 185 } 186 if (!this->compr_buf) { 187 spin_unlock(&jffs2_compressor_list_lock); 188 tmp_buf = kmalloc(orig_slen, GFP_KERNEL); 189 spin_lock(&jffs2_compressor_list_lock); 190 if (!tmp_buf) { 191 pr_warn("JFFS2: No memory for compressor allocation. (%d bytes)\n", 192 orig_slen); 193 continue; 194 } 195 else { 196 this->compr_buf = tmp_buf; 197 this->compr_buf_size = orig_slen; 198 } 199 } 200 this->usecount++; 201 spin_unlock(&jffs2_compressor_list_lock); 202 *datalen = orig_slen; 203 *cdatalen = orig_dlen; 204 compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen); 205 spin_lock(&jffs2_compressor_list_lock); 206 this->usecount--; 207 if (!compr_ret) { 208 if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen)) 209 && (*cdatalen < *datalen)) { 210 best_dlen = *cdatalen; 211 best_slen = *datalen; 212 best = this; 213 } 214 } 215 } 216 if (best_dlen) { 217 *cdatalen = best_dlen; 218 *datalen = best_slen; 219 output_buf = best->compr_buf; 220 best->compr_buf = NULL; 221 best->compr_buf_size = 0; 222 best->stat_compr_blocks++; 223 best->stat_compr_orig_size += best_slen; 224 best->stat_compr_new_size += best_dlen; 225 ret = best->compr; 226 *cpage_out = output_buf; 227 } 228 spin_unlock(&jffs2_compressor_list_lock); 229 break; 230 case JFFS2_COMPR_MODE_FORCELZO: 231 ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in, 232 cpage_out, datalen, cdatalen); 233 break; 234 case JFFS2_COMPR_MODE_FORCEZLIB: 235 ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in, 236 cpage_out, datalen, cdatalen); 237 break; 238 default: 239 pr_err("JFFS2: unknown compression mode\n"); 240 } 241 242 if (ret == JFFS2_COMPR_NONE) { 243 *cpage_out = data_in; 244 *datalen = *cdatalen; 245 none_stat_compr_blocks++; 246 none_stat_compr_size += *datalen; 247 } 248 return ret; 249 } 250 251 int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 252 uint16_t comprtype, unsigned char *cdata_in, 253 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) 254 { 255 struct jffs2_compressor *this; 256 int ret; 257 258 /* Older code had a bug where it would write non-zero 'usercompr' 259 fields. Deal with it. */ 260 if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB) 261 comprtype &= 0xff; 262 263 switch (comprtype & 0xff) { 264 case JFFS2_COMPR_NONE: 265 /* This should be special-cased elsewhere, but we might as well deal with it */ 266 memcpy(data_out, cdata_in, datalen); 267 none_stat_decompr_blocks++; 268 break; 269 case JFFS2_COMPR_ZERO: 270 memset(data_out, 0, datalen); 271 break; 272 default: 273 spin_lock(&jffs2_compressor_list_lock); 274 list_for_each_entry(this, &jffs2_compressor_list, list) { 275 if (comprtype == this->compr) { 276 this->usecount++; 277 spin_unlock(&jffs2_compressor_list_lock); 278 ret = this->decompress(cdata_in, data_out, cdatalen, datalen); 279 spin_lock(&jffs2_compressor_list_lock); 280 if (ret) { 281 pr_warn("Decompressor \"%s\" returned %d\n", 282 this->name, ret); 283 } 284 else { 285 this->stat_decompr_blocks++; 286 } 287 this->usecount--; 288 spin_unlock(&jffs2_compressor_list_lock); 289 return ret; 290 } 291 } 292 pr_warn("JFFS2 compression type 0x%02x not available\n", 293 comprtype); 294 spin_unlock(&jffs2_compressor_list_lock); 295 return -EIO; 296 } 297 return 0; 298 } 299 300 int jffs2_register_compressor(struct jffs2_compressor *comp) 301 { 302 struct jffs2_compressor *this; 303 304 if (!comp->name) { 305 pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n"); 306 return -1; 307 } 308 comp->compr_buf_size=0; 309 comp->compr_buf=NULL; 310 comp->usecount=0; 311 comp->stat_compr_orig_size=0; 312 comp->stat_compr_new_size=0; 313 comp->stat_compr_blocks=0; 314 comp->stat_decompr_blocks=0; 315 jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name); 316 317 spin_lock(&jffs2_compressor_list_lock); 318 319 list_for_each_entry(this, &jffs2_compressor_list, list) { 320 if (this->priority < comp->priority) { 321 list_add(&comp->list, this->list.prev); 322 goto out; 323 } 324 } 325 list_add_tail(&comp->list, &jffs2_compressor_list); 326 out: 327 D2(list_for_each_entry(this, &jffs2_compressor_list, list) { 328 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); 329 }) 330 331 spin_unlock(&jffs2_compressor_list_lock); 332 333 return 0; 334 } 335 336 int jffs2_unregister_compressor(struct jffs2_compressor *comp) 337 { 338 D2(struct jffs2_compressor *this); 339 340 jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name); 341 342 spin_lock(&jffs2_compressor_list_lock); 343 344 if (comp->usecount) { 345 spin_unlock(&jffs2_compressor_list_lock); 346 pr_warn("JFFS2: Compressor module is in use. Unregister failed.\n"); 347 return -1; 348 } 349 list_del(&comp->list); 350 351 D2(list_for_each_entry(this, &jffs2_compressor_list, list) { 352 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); 353 }) 354 spin_unlock(&jffs2_compressor_list_lock); 355 return 0; 356 } 357 358 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) 359 { 360 if (orig != comprbuf) 361 kfree(comprbuf); 362 } 363 364 int __init jffs2_compressors_init(void) 365 { 366 /* Registering compressors */ 367 #ifdef CONFIG_JFFS2_ZLIB 368 jffs2_zlib_init(); 369 #endif 370 #ifdef CONFIG_JFFS2_RTIME 371 jffs2_rtime_init(); 372 #endif 373 #ifdef CONFIG_JFFS2_RUBIN 374 jffs2_rubinmips_init(); 375 jffs2_dynrubin_init(); 376 #endif 377 #ifdef CONFIG_JFFS2_LZO 378 jffs2_lzo_init(); 379 #endif 380 /* Setting default compression mode */ 381 #ifdef CONFIG_JFFS2_CMODE_NONE 382 jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; 383 jffs2_dbg(1, "JFFS2: default compression mode: none\n"); 384 #else 385 #ifdef CONFIG_JFFS2_CMODE_SIZE 386 jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; 387 jffs2_dbg(1, "JFFS2: default compression mode: size\n"); 388 #else 389 #ifdef CONFIG_JFFS2_CMODE_FAVOURLZO 390 jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO; 391 jffs2_dbg(1, "JFFS2: default compression mode: favourlzo\n"); 392 #else 393 jffs2_dbg(1, "JFFS2: default compression mode: priority\n"); 394 #endif 395 #endif 396 #endif 397 return 0; 398 } 399 400 int jffs2_compressors_exit(void) 401 { 402 /* Unregistering compressors */ 403 #ifdef CONFIG_JFFS2_LZO 404 jffs2_lzo_exit(); 405 #endif 406 #ifdef CONFIG_JFFS2_RUBIN 407 jffs2_dynrubin_exit(); 408 jffs2_rubinmips_exit(); 409 #endif 410 #ifdef CONFIG_JFFS2_RTIME 411 jffs2_rtime_exit(); 412 #endif 413 #ifdef CONFIG_JFFS2_ZLIB 414 jffs2_zlib_exit(); 415 #endif 416 return 0; 417 } 418