zcomp.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * Copyright (C) 2014 Sergey Senozhatsky.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/string.h>
  11. #include <linux/err.h>
  12. #include <linux/slab.h>
  13. #include <linux/wait.h>
  14. #include <linux/sched.h>
  15. #include <linux/cpu.h>
  16. #include <linux/crypto.h>
  17. #include "zcomp.h"
  18. static const char * const backends[] = {
  19. "lzo",
  20. #if IS_ENABLED(CONFIG_CRYPTO_LZ4)
  21. "lz4",
  22. #endif
  23. #if IS_ENABLED(CONFIG_CRYPTO_DEFLATE)
  24. "deflate",
  25. #endif
  26. #if IS_ENABLED(CONFIG_CRYPTO_LZ4HC)
  27. "lz4hc",
  28. #endif
  29. #if IS_ENABLED(CONFIG_CRYPTO_842)
  30. "842",
  31. #endif
  32. NULL
  33. };
  34. static void zcomp_strm_free(struct zcomp_strm *zstrm)
  35. {
  36. if (!IS_ERR_OR_NULL(zstrm->tfm))
  37. crypto_free_comp(zstrm->tfm);
  38. free_pages((unsigned long)zstrm->buffer, 1);
  39. kfree(zstrm);
  40. }
  41. /*
  42. * allocate new zcomp_strm structure with ->tfm initialized by
  43. * backend, return NULL on error
  44. */
  45. static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
  46. {
  47. struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
  48. if (!zstrm)
  49. return NULL;
  50. zstrm->tfm = crypto_alloc_comp(comp->name, 0, 0);
  51. /*
  52. * allocate 2 pages. 1 for compressed data, plus 1 extra for the
  53. * case when compressed size is larger than the original one
  54. */
  55. zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
  56. if (IS_ERR_OR_NULL(zstrm->tfm) || !zstrm->buffer) {
  57. zcomp_strm_free(zstrm);
  58. zstrm = NULL;
  59. }
  60. return zstrm;
  61. }
  62. bool zcomp_available_algorithm(const char *comp)
  63. {
  64. int i = 0;
  65. while (backends[i]) {
  66. if (sysfs_streq(comp, backends[i]))
  67. return true;
  68. i++;
  69. }
  70. /*
  71. * Crypto does not ignore a trailing new line symbol,
  72. * so make sure you don't supply a string containing
  73. * one.
  74. * This also means that we permit zcomp initialisation
  75. * with any compressing algorithm known to crypto api.
  76. */
  77. return crypto_has_comp(comp, 0, 0) == 1;
  78. }
  79. /* show available compressors */
  80. ssize_t zcomp_available_show(const char *comp, char *buf)
  81. {
  82. bool known_algorithm = false;
  83. ssize_t sz = 0;
  84. int i = 0;
  85. for (; backends[i]; i++) {
  86. if (!strcmp(comp, backends[i])) {
  87. known_algorithm = true;
  88. sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
  89. "[%s] ", backends[i]);
  90. } else {
  91. sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
  92. "%s ", backends[i]);
  93. }
  94. }
  95. /*
  96. * Out-of-tree module known to crypto api or a missing
  97. * entry in `backends'.
  98. */
  99. if (!known_algorithm && crypto_has_comp(comp, 0, 0) == 1)
  100. sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
  101. "[%s] ", comp);
  102. sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
  103. return sz;
  104. }
  105. struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
  106. {
  107. return *get_cpu_ptr(comp->stream);
  108. }
  109. void zcomp_stream_put(struct zcomp *comp)
  110. {
  111. put_cpu_ptr(comp->stream);
  112. }
  113. int zcomp_compress(struct zcomp_strm *zstrm,
  114. const void *src, unsigned int *dst_len)
  115. {
  116. /*
  117. * Our dst memory (zstrm->buffer) is always `2 * PAGE_SIZE' sized
  118. * because sometimes we can endup having a bigger compressed data
  119. * due to various reasons: for example compression algorithms tend
  120. * to add some padding to the compressed buffer. Speaking of padding,
  121. * comp algorithm `842' pads the compressed length to multiple of 8
  122. * and returns -ENOSP when the dst memory is not big enough, which
  123. * is not something that ZRAM wants to see. We can handle the
  124. * `compressed_size > PAGE_SIZE' case easily in ZRAM, but when we
  125. * receive -ERRNO from the compressing backend we can't help it
  126. * anymore. To make `842' happy we need to tell the exact size of
  127. * the dst buffer, zram_drv will take care of the fact that
  128. * compressed buffer is too big.
  129. */
  130. *dst_len = PAGE_SIZE * 2;
  131. return crypto_comp_compress(zstrm->tfm,
  132. src, PAGE_SIZE,
  133. zstrm->buffer, dst_len);
  134. }
  135. int zcomp_decompress(struct zcomp_strm *zstrm,
  136. const void *src, unsigned int src_len, void *dst)
  137. {
  138. unsigned int dst_len = PAGE_SIZE;
  139. return crypto_comp_decompress(zstrm->tfm,
  140. src, src_len,
  141. dst, &dst_len);
  142. }
  143. static int __zcomp_cpu_notifier(struct zcomp *comp,
  144. unsigned long action, unsigned long cpu)
  145. {
  146. struct zcomp_strm *zstrm;
  147. switch (action) {
  148. case CPU_UP_PREPARE:
  149. if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
  150. break;
  151. zstrm = zcomp_strm_alloc(comp);
  152. if (IS_ERR_OR_NULL(zstrm)) {
  153. pr_err("Can't allocate a compression stream\n");
  154. return NOTIFY_BAD;
  155. }
  156. *per_cpu_ptr(comp->stream, cpu) = zstrm;
  157. break;
  158. case CPU_DEAD:
  159. case CPU_UP_CANCELED:
  160. zstrm = *per_cpu_ptr(comp->stream, cpu);
  161. if (!IS_ERR_OR_NULL(zstrm))
  162. zcomp_strm_free(zstrm);
  163. *per_cpu_ptr(comp->stream, cpu) = NULL;
  164. break;
  165. default:
  166. break;
  167. }
  168. return NOTIFY_OK;
  169. }
  170. static int zcomp_cpu_notifier(struct notifier_block *nb,
  171. unsigned long action, void *pcpu)
  172. {
  173. unsigned long cpu = (unsigned long)pcpu;
  174. struct zcomp *comp = container_of(nb, typeof(*comp), notifier);
  175. return __zcomp_cpu_notifier(comp, action, cpu);
  176. }
  177. static int zcomp_init(struct zcomp *comp)
  178. {
  179. unsigned long cpu;
  180. int ret;
  181. comp->notifier.notifier_call = zcomp_cpu_notifier;
  182. comp->stream = alloc_percpu(struct zcomp_strm *);
  183. if (!comp->stream)
  184. return -ENOMEM;
  185. cpu_notifier_register_begin();
  186. for_each_online_cpu(cpu) {
  187. ret = __zcomp_cpu_notifier(comp, CPU_UP_PREPARE, cpu);
  188. if (ret == NOTIFY_BAD)
  189. goto cleanup;
  190. }
  191. __register_cpu_notifier(&comp->notifier);
  192. cpu_notifier_register_done();
  193. return 0;
  194. cleanup:
  195. for_each_online_cpu(cpu)
  196. __zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
  197. cpu_notifier_register_done();
  198. return -ENOMEM;
  199. }
  200. void zcomp_destroy(struct zcomp *comp)
  201. {
  202. unsigned long cpu;
  203. cpu_notifier_register_begin();
  204. for_each_online_cpu(cpu)
  205. __zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
  206. __unregister_cpu_notifier(&comp->notifier);
  207. cpu_notifier_register_done();
  208. free_percpu(comp->stream);
  209. kfree(comp);
  210. }
  211. /*
  212. * search available compressors for requested algorithm.
  213. * allocate new zcomp and initialize it. return compressing
  214. * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
  215. * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
  216. * case of allocation error, or any other error potentially
  217. * returned by zcomp_init().
  218. */
  219. struct zcomp *zcomp_create(const char *compress)
  220. {
  221. struct zcomp *comp;
  222. int error;
  223. if (!zcomp_available_algorithm(compress))
  224. return ERR_PTR(-EINVAL);
  225. comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
  226. if (!comp)
  227. return ERR_PTR(-ENOMEM);
  228. comp->name = compress;
  229. error = zcomp_init(comp);
  230. if (error) {
  231. kfree(comp);
  232. return ERR_PTR(error);
  233. }
  234. return comp;
  235. }