zcomp.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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_LZ4HC)
  24. "lz4hc",
  25. #endif
  26. #if IS_ENABLED(CONFIG_CRYPTO_842)
  27. "842",
  28. #endif
  29. #if IS_ENABLED(CONFIG_CRYPTO_ZSTD)
  30. "zstd",
  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;
  65. i = __sysfs_match_string(backends, -1, comp);
  66. if (i >= 0)
  67. return true;
  68. /*
  69. * Crypto does not ignore a trailing new line symbol,
  70. * so make sure you don't supply a string containing
  71. * one.
  72. * This also means that we permit zcomp initialisation
  73. * with any compressing algorithm known to crypto api.
  74. */
  75. return crypto_has_comp(comp, 0, 0) == 1;
  76. }
  77. /* show available compressors */
  78. ssize_t zcomp_available_show(const char *comp, char *buf)
  79. {
  80. bool known_algorithm = false;
  81. ssize_t sz = 0;
  82. int i = 0;
  83. for (; backends[i]; i++) {
  84. if (!strcmp(comp, backends[i])) {
  85. known_algorithm = true;
  86. sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
  87. "[%s] ", backends[i]);
  88. } else {
  89. sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
  90. "%s ", backends[i]);
  91. }
  92. }
  93. /*
  94. * Out-of-tree module known to crypto api or a missing
  95. * entry in `backends'.
  96. */
  97. if (!known_algorithm && crypto_has_comp(comp, 0, 0) == 1)
  98. sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
  99. "[%s] ", comp);
  100. sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
  101. return sz;
  102. }
  103. struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
  104. {
  105. return *get_cpu_ptr(comp->stream);
  106. }
  107. void zcomp_stream_put(struct zcomp *comp)
  108. {
  109. put_cpu_ptr(comp->stream);
  110. }
  111. int zcomp_compress(struct zcomp_strm *zstrm,
  112. const void *src, unsigned int *dst_len)
  113. {
  114. /*
  115. * Our dst memory (zstrm->buffer) is always `2 * PAGE_SIZE' sized
  116. * because sometimes we can endup having a bigger compressed data
  117. * due to various reasons: for example compression algorithms tend
  118. * to add some padding to the compressed buffer. Speaking of padding,
  119. * comp algorithm `842' pads the compressed length to multiple of 8
  120. * and returns -ENOSP when the dst memory is not big enough, which
  121. * is not something that ZRAM wants to see. We can handle the
  122. * `compressed_size > PAGE_SIZE' case easily in ZRAM, but when we
  123. * receive -ERRNO from the compressing backend we can't help it
  124. * anymore. To make `842' happy we need to tell the exact size of
  125. * the dst buffer, zram_drv will take care of the fact that
  126. * compressed buffer is too big.
  127. */
  128. *dst_len = PAGE_SIZE * 2;
  129. return crypto_comp_compress(zstrm->tfm,
  130. src, PAGE_SIZE,
  131. zstrm->buffer, dst_len);
  132. }
  133. int zcomp_decompress(struct zcomp_strm *zstrm,
  134. const void *src, unsigned int src_len, void *dst)
  135. {
  136. unsigned int dst_len = PAGE_SIZE;
  137. return crypto_comp_decompress(zstrm->tfm,
  138. src, src_len,
  139. dst, &dst_len);
  140. }
  141. int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
  142. {
  143. struct zcomp *comp = hlist_entry(node, struct zcomp, node);
  144. struct zcomp_strm *zstrm;
  145. if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
  146. return 0;
  147. zstrm = zcomp_strm_alloc(comp);
  148. if (IS_ERR_OR_NULL(zstrm)) {
  149. pr_err("Can't allocate a compression stream\n");
  150. return -ENOMEM;
  151. }
  152. *per_cpu_ptr(comp->stream, cpu) = zstrm;
  153. return 0;
  154. }
  155. int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node)
  156. {
  157. struct zcomp *comp = hlist_entry(node, struct zcomp, node);
  158. struct zcomp_strm *zstrm;
  159. zstrm = *per_cpu_ptr(comp->stream, cpu);
  160. if (!IS_ERR_OR_NULL(zstrm))
  161. zcomp_strm_free(zstrm);
  162. *per_cpu_ptr(comp->stream, cpu) = NULL;
  163. return 0;
  164. }
  165. static int zcomp_init(struct zcomp *comp)
  166. {
  167. int ret;
  168. comp->stream = alloc_percpu(struct zcomp_strm *);
  169. if (!comp->stream)
  170. return -ENOMEM;
  171. ret = cpuhp_state_add_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
  172. if (ret < 0)
  173. goto cleanup;
  174. return 0;
  175. cleanup:
  176. free_percpu(comp->stream);
  177. return ret;
  178. }
  179. void zcomp_destroy(struct zcomp *comp)
  180. {
  181. cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
  182. free_percpu(comp->stream);
  183. kfree(comp);
  184. }
  185. /*
  186. * search available compressors for requested algorithm.
  187. * allocate new zcomp and initialize it. return compressing
  188. * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
  189. * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
  190. * case of allocation error, or any other error potentially
  191. * returned by zcomp_init().
  192. */
  193. struct zcomp *zcomp_create(const char *compress)
  194. {
  195. struct zcomp *comp;
  196. int error;
  197. if (!zcomp_available_algorithm(compress))
  198. return ERR_PTR(-EINVAL);
  199. comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
  200. if (!comp)
  201. return ERR_PTR(-ENOMEM);
  202. comp->name = compress;
  203. error = zcomp_init(comp);
  204. if (error) {
  205. kfree(comp);
  206. return ERR_PTR(error);
  207. }
  208. return comp;
  209. }