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