compr.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * JFFS2 -- Journalling Flash File System, Version 2.
  3. *
  4. * Copyright © 2001-2007 Red Hat, Inc.
  5. * Created by Arjan van de Ven <arjanv@redhat.com>
  6. *
  7. * Copyright © 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. *
  12. */
  13. #include "compr.h"
  14. static DEFINE_SPINLOCK(jffs2_compressor_list_lock);
  15. /* Available compressors are on this list */
  16. static LIST_HEAD(jffs2_compressor_list);
  17. /* Actual compression mode */
  18. static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
  19. /* Statistics for blocks stored without compression */
  20. static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
  21. /* jffs2_compress:
  22. * @data: Pointer to uncompressed data
  23. * @cdata: Pointer to returned pointer to buffer for compressed data
  24. * @datalen: On entry, holds the amount of data available for compression.
  25. * On exit, expected to hold the amount of data actually compressed.
  26. * @cdatalen: On entry, holds the amount of space available for compressed
  27. * data. On exit, expected to hold the actual size of the compressed
  28. * data.
  29. *
  30. * Returns: Lower byte to be stored with data indicating compression type used.
  31. * Zero is used to show that the data could not be compressed - the
  32. * compressed version was actually larger than the original.
  33. * Upper byte will be used later. (soon)
  34. *
  35. * If the cdata buffer isn't large enough to hold all the uncompressed data,
  36. * jffs2_compress should compress as much as will fit, and should set
  37. * *datalen accordingly to show the amount of data which were compressed.
  38. */
  39. uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
  40. unsigned char *data_in, unsigned char **cpage_out,
  41. uint32_t *datalen, uint32_t *cdatalen)
  42. {
  43. int ret = JFFS2_COMPR_NONE;
  44. int compr_ret;
  45. struct jffs2_compressor *this, *best=NULL;
  46. unsigned char *output_buf = NULL, *tmp_buf;
  47. uint32_t orig_slen, orig_dlen;
  48. uint32_t best_slen=0, best_dlen=0;
  49. switch (jffs2_compression_mode) {
  50. case JFFS2_COMPR_MODE_NONE:
  51. break;
  52. case JFFS2_COMPR_MODE_PRIORITY:
  53. output_buf = kmalloc(*cdatalen,GFP_KERNEL);
  54. if (!output_buf) {
  55. printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
  56. goto out;
  57. }
  58. orig_slen = *datalen;
  59. orig_dlen = *cdatalen;
  60. spin_lock(&jffs2_compressor_list_lock);
  61. list_for_each_entry(this, &jffs2_compressor_list, list) {
  62. /* Skip decompress-only backwards-compatibility and disabled modules */
  63. if ((!this->compress)||(this->disabled))
  64. continue;
  65. this->usecount++;
  66. spin_unlock(&jffs2_compressor_list_lock);
  67. *datalen = orig_slen;
  68. *cdatalen = orig_dlen;
  69. compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
  70. spin_lock(&jffs2_compressor_list_lock);
  71. this->usecount--;
  72. if (!compr_ret) {
  73. ret = this->compr;
  74. this->stat_compr_blocks++;
  75. this->stat_compr_orig_size += *datalen;
  76. this->stat_compr_new_size += *cdatalen;
  77. break;
  78. }
  79. }
  80. spin_unlock(&jffs2_compressor_list_lock);
  81. if (ret == JFFS2_COMPR_NONE)
  82. kfree(output_buf);
  83. break;
  84. case JFFS2_COMPR_MODE_SIZE:
  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 backwards-compatibility and disabled modules */
  90. if ((!this->compress)||(this->disabled))
  91. continue;
  92. /* Allocating memory for output buffer if necessary */
  93. if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
  94. spin_unlock(&jffs2_compressor_list_lock);
  95. kfree(this->compr_buf);
  96. spin_lock(&jffs2_compressor_list_lock);
  97. this->compr_buf_size=0;
  98. this->compr_buf=NULL;
  99. }
  100. if (!this->compr_buf) {
  101. spin_unlock(&jffs2_compressor_list_lock);
  102. tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
  103. spin_lock(&jffs2_compressor_list_lock);
  104. if (!tmp_buf) {
  105. printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
  106. continue;
  107. }
  108. else {
  109. this->compr_buf = tmp_buf;
  110. this->compr_buf_size = orig_dlen;
  111. }
  112. }
  113. this->usecount++;
  114. spin_unlock(&jffs2_compressor_list_lock);
  115. *datalen = orig_slen;
  116. *cdatalen = orig_dlen;
  117. compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
  118. spin_lock(&jffs2_compressor_list_lock);
  119. this->usecount--;
  120. if (!compr_ret) {
  121. if ((!best_dlen)||(best_dlen>*cdatalen)) {
  122. best_dlen = *cdatalen;
  123. best_slen = *datalen;
  124. best = this;
  125. }
  126. }
  127. }
  128. if (best_dlen) {
  129. *cdatalen = best_dlen;
  130. *datalen = best_slen;
  131. output_buf = best->compr_buf;
  132. best->compr_buf = NULL;
  133. best->compr_buf_size = 0;
  134. best->stat_compr_blocks++;
  135. best->stat_compr_orig_size += best_slen;
  136. best->stat_compr_new_size += best_dlen;
  137. ret = best->compr;
  138. }
  139. spin_unlock(&jffs2_compressor_list_lock);
  140. break;
  141. default:
  142. printk(KERN_ERR "JFFS2: unknow compression mode.\n");
  143. }
  144. out:
  145. if (ret == JFFS2_COMPR_NONE) {
  146. *cpage_out = data_in;
  147. *datalen = *cdatalen;
  148. none_stat_compr_blocks++;
  149. none_stat_compr_size += *datalen;
  150. }
  151. else {
  152. *cpage_out = output_buf;
  153. }
  154. return ret;
  155. }
  156. int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
  157. uint16_t comprtype, unsigned char *cdata_in,
  158. unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
  159. {
  160. struct jffs2_compressor *this;
  161. int ret;
  162. /* Older code had a bug where it would write non-zero 'usercompr'
  163. fields. Deal with it. */
  164. if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB)
  165. comprtype &= 0xff;
  166. switch (comprtype & 0xff) {
  167. case JFFS2_COMPR_NONE:
  168. /* This should be special-cased elsewhere, but we might as well deal with it */
  169. memcpy(data_out, cdata_in, datalen);
  170. none_stat_decompr_blocks++;
  171. break;
  172. case JFFS2_COMPR_ZERO:
  173. memset(data_out, 0, datalen);
  174. break;
  175. default:
  176. spin_lock(&jffs2_compressor_list_lock);
  177. list_for_each_entry(this, &jffs2_compressor_list, list) {
  178. if (comprtype == this->compr) {
  179. this->usecount++;
  180. spin_unlock(&jffs2_compressor_list_lock);
  181. ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
  182. spin_lock(&jffs2_compressor_list_lock);
  183. if (ret) {
  184. printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
  185. }
  186. else {
  187. this->stat_decompr_blocks++;
  188. }
  189. this->usecount--;
  190. spin_unlock(&jffs2_compressor_list_lock);
  191. return ret;
  192. }
  193. }
  194. printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype);
  195. spin_unlock(&jffs2_compressor_list_lock);
  196. return -EIO;
  197. }
  198. return 0;
  199. }
  200. int jffs2_register_compressor(struct jffs2_compressor *comp)
  201. {
  202. struct jffs2_compressor *this;
  203. if (!comp->name) {
  204. printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
  205. return -1;
  206. }
  207. comp->compr_buf_size=0;
  208. comp->compr_buf=NULL;
  209. comp->usecount=0;
  210. comp->stat_compr_orig_size=0;
  211. comp->stat_compr_new_size=0;
  212. comp->stat_compr_blocks=0;
  213. comp->stat_decompr_blocks=0;
  214. D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
  215. spin_lock(&jffs2_compressor_list_lock);
  216. list_for_each_entry(this, &jffs2_compressor_list, list) {
  217. if (this->priority < comp->priority) {
  218. list_add(&comp->list, this->list.prev);
  219. goto out;
  220. }
  221. }
  222. list_add_tail(&comp->list, &jffs2_compressor_list);
  223. out:
  224. D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
  225. printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
  226. })
  227. spin_unlock(&jffs2_compressor_list_lock);
  228. return 0;
  229. }
  230. int jffs2_unregister_compressor(struct jffs2_compressor *comp)
  231. {
  232. D2(struct jffs2_compressor *this;)
  233. D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
  234. spin_lock(&jffs2_compressor_list_lock);
  235. if (comp->usecount) {
  236. spin_unlock(&jffs2_compressor_list_lock);
  237. printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
  238. return -1;
  239. }
  240. list_del(&comp->list);
  241. D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
  242. printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
  243. })
  244. spin_unlock(&jffs2_compressor_list_lock);
  245. return 0;
  246. }
  247. void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
  248. {
  249. if (orig != comprbuf)
  250. kfree(comprbuf);
  251. }
  252. int __init jffs2_compressors_init(void)
  253. {
  254. /* Registering compressors */
  255. #ifdef CONFIG_JFFS2_ZLIB
  256. jffs2_zlib_init();
  257. #endif
  258. #ifdef CONFIG_JFFS2_RTIME
  259. jffs2_rtime_init();
  260. #endif
  261. #ifdef CONFIG_JFFS2_RUBIN
  262. jffs2_rubinmips_init();
  263. jffs2_dynrubin_init();
  264. #endif
  265. /* Setting default compression mode */
  266. #ifdef CONFIG_JFFS2_CMODE_NONE
  267. jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
  268. D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
  269. #else
  270. #ifdef CONFIG_JFFS2_CMODE_SIZE
  271. jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
  272. D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
  273. #else
  274. D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
  275. #endif
  276. #endif
  277. return 0;
  278. }
  279. int jffs2_compressors_exit(void)
  280. {
  281. /* Unregistering compressors */
  282. #ifdef CONFIG_JFFS2_RUBIN
  283. jffs2_dynrubin_exit();
  284. jffs2_rubinmips_exit();
  285. #endif
  286. #ifdef CONFIG_JFFS2_RTIME
  287. jffs2_rtime_exit();
  288. #endif
  289. #ifdef CONFIG_JFFS2_ZLIB
  290. jffs2_zlib_exit();
  291. #endif
  292. return 0;
  293. }