1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2014 Sergey Senozhatsky.
6 #include <linux/kernel.h>
7 #include <linux/string.h>
9 #include <linux/slab.h>
10 #include <linux/wait.h>
11 #include <linux/sched.h>
12 #include <linux/cpu.h>
13 #include <linux/crypto.h>
17 static const char * const backends
[] = {
20 #if IS_ENABLED(CONFIG_CRYPTO_LZ4)
23 #if IS_ENABLED(CONFIG_CRYPTO_LZ4HC)
26 #if IS_ENABLED(CONFIG_CRYPTO_842)
29 #if IS_ENABLED(CONFIG_CRYPTO_ZSTD)
35 static void zcomp_strm_free(struct zcomp_strm
*zstrm
)
37 if (!IS_ERR_OR_NULL(zstrm
->tfm
))
38 crypto_free_comp(zstrm
->tfm
);
39 free_pages((unsigned long)zstrm
->buffer
, 1);
44 * allocate new zcomp_strm structure with ->tfm initialized by
45 * backend, return NULL on error
47 static struct zcomp_strm
*zcomp_strm_alloc(struct zcomp
*comp
)
49 struct zcomp_strm
*zstrm
= kmalloc(sizeof(*zstrm
), GFP_KERNEL
);
53 zstrm
->tfm
= crypto_alloc_comp(comp
->name
, 0, 0);
55 * allocate 2 pages. 1 for compressed data, plus 1 extra for the
56 * case when compressed size is larger than the original one
58 zstrm
->buffer
= (void *)__get_free_pages(GFP_KERNEL
| __GFP_ZERO
, 1);
59 if (IS_ERR_OR_NULL(zstrm
->tfm
) || !zstrm
->buffer
) {
60 zcomp_strm_free(zstrm
);
66 bool zcomp_available_algorithm(const char *comp
)
70 i
= __sysfs_match_string(backends
, -1, comp
);
75 * Crypto does not ignore a trailing new line symbol,
76 * so make sure you don't supply a string containing
78 * This also means that we permit zcomp initialisation
79 * with any compressing algorithm known to crypto api.
81 return crypto_has_comp(comp
, 0, 0) == 1;
84 /* show available compressors */
85 ssize_t
zcomp_available_show(const char *comp
, char *buf
)
87 bool known_algorithm
= false;
91 for (; backends
[i
]; i
++) {
92 if (!strcmp(comp
, backends
[i
])) {
93 known_algorithm
= true;
94 sz
+= scnprintf(buf
+ sz
, PAGE_SIZE
- sz
- 2,
95 "[%s] ", backends
[i
]);
97 sz
+= scnprintf(buf
+ sz
, PAGE_SIZE
- sz
- 2,
103 * Out-of-tree module known to crypto api or a missing
104 * entry in `backends'.
106 if (!known_algorithm
&& crypto_has_comp(comp
, 0, 0) == 1)
107 sz
+= scnprintf(buf
+ sz
, PAGE_SIZE
- sz
- 2,
110 sz
+= scnprintf(buf
+ sz
, PAGE_SIZE
- sz
, "\n");
114 struct zcomp_strm
*zcomp_stream_get(struct zcomp
*comp
)
116 return *get_cpu_ptr(comp
->stream
);
119 void zcomp_stream_put(struct zcomp
*comp
)
121 put_cpu_ptr(comp
->stream
);
124 int zcomp_compress(struct zcomp_strm
*zstrm
,
125 const void *src
, unsigned int *dst_len
)
128 * Our dst memory (zstrm->buffer) is always `2 * PAGE_SIZE' sized
129 * because sometimes we can endup having a bigger compressed data
130 * due to various reasons: for example compression algorithms tend
131 * to add some padding to the compressed buffer. Speaking of padding,
132 * comp algorithm `842' pads the compressed length to multiple of 8
133 * and returns -ENOSP when the dst memory is not big enough, which
134 * is not something that ZRAM wants to see. We can handle the
135 * `compressed_size > PAGE_SIZE' case easily in ZRAM, but when we
136 * receive -ERRNO from the compressing backend we can't help it
137 * anymore. To make `842' happy we need to tell the exact size of
138 * the dst buffer, zram_drv will take care of the fact that
139 * compressed buffer is too big.
141 *dst_len
= PAGE_SIZE
* 2;
143 return crypto_comp_compress(zstrm
->tfm
,
145 zstrm
->buffer
, dst_len
);
148 int zcomp_decompress(struct zcomp_strm
*zstrm
,
149 const void *src
, unsigned int src_len
, void *dst
)
151 unsigned int dst_len
= PAGE_SIZE
;
153 return crypto_comp_decompress(zstrm
->tfm
,
158 int zcomp_cpu_up_prepare(unsigned int cpu
, struct hlist_node
*node
)
160 struct zcomp
*comp
= hlist_entry(node
, struct zcomp
, node
);
161 struct zcomp_strm
*zstrm
;
163 if (WARN_ON(*per_cpu_ptr(comp
->stream
, cpu
)))
166 zstrm
= zcomp_strm_alloc(comp
);
167 if (IS_ERR_OR_NULL(zstrm
)) {
168 pr_err("Can't allocate a compression stream\n");
171 *per_cpu_ptr(comp
->stream
, cpu
) = zstrm
;
175 int zcomp_cpu_dead(unsigned int cpu
, struct hlist_node
*node
)
177 struct zcomp
*comp
= hlist_entry(node
, struct zcomp
, node
);
178 struct zcomp_strm
*zstrm
;
180 zstrm
= *per_cpu_ptr(comp
->stream
, cpu
);
181 if (!IS_ERR_OR_NULL(zstrm
))
182 zcomp_strm_free(zstrm
);
183 *per_cpu_ptr(comp
->stream
, cpu
) = NULL
;
187 static int zcomp_init(struct zcomp
*comp
)
191 comp
->stream
= alloc_percpu(struct zcomp_strm
*);
195 ret
= cpuhp_state_add_instance(CPUHP_ZCOMP_PREPARE
, &comp
->node
);
201 free_percpu(comp
->stream
);
205 void zcomp_destroy(struct zcomp
*comp
)
207 cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE
, &comp
->node
);
208 free_percpu(comp
->stream
);
213 * search available compressors for requested algorithm.
214 * allocate new zcomp and initialize it. return compressing
215 * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
216 * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
217 * case of allocation error, or any other error potentially
218 * returned by zcomp_init().
220 struct zcomp
*zcomp_create(const char *compress
)
225 if (!zcomp_available_algorithm(compress
))
226 return ERR_PTR(-EINVAL
);
228 comp
= kzalloc(sizeof(struct zcomp
), GFP_KERNEL
);
230 return ERR_PTR(-ENOMEM
);
232 comp
->name
= compress
;
233 error
= zcomp_init(comp
);
236 return ERR_PTR(error
);