hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/block/zram/zcomp.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * 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.
84 */
95
106 #include <linux/kernel.h>
....@@ -20,6 +16,7 @@
2016
2117 static const char * const backends[] = {
2218 "lzo",
19
+ "lzo-rle",
2320 #if IS_ENABLED(CONFIG_CRYPTO_LZ4)
2421 "lz4",
2522 #endif
....@@ -32,7 +29,6 @@
3229 #if IS_ENABLED(CONFIG_CRYPTO_ZSTD)
3330 "zstd",
3431 #endif
35
- NULL
3632 };
3733
3834 static void zcomp_strm_free(struct zcomp_strm *zstrm)
....@@ -40,19 +36,16 @@
4036 if (!IS_ERR_OR_NULL(zstrm->tfm))
4137 crypto_free_comp(zstrm->tfm);
4238 free_pages((unsigned long)zstrm->buffer, 1);
43
- kfree(zstrm);
39
+ zstrm->tfm = NULL;
40
+ zstrm->buffer = NULL;
4441 }
4542
4643 /*
47
- * allocate new zcomp_strm structure with ->tfm initialized by
48
- * backend, return NULL on error
44
+ * Initialize zcomp_strm structure with ->tfm initialized by backend, and
45
+ * ->buffer. Return a negative value on error.
4946 */
50
-static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
47
+static int zcomp_strm_init(struct zcomp_strm *zstrm, struct zcomp *comp)
5148 {
52
- struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
53
- if (!zstrm)
54
- return NULL;
55
-
5649 zstrm->tfm = crypto_alloc_comp(comp->name, 0, 0);
5750 /*
5851 * allocate 2 pages. 1 for compressed data, plus 1 extra for the
....@@ -61,19 +54,13 @@
6154 zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
6255 if (IS_ERR_OR_NULL(zstrm->tfm) || !zstrm->buffer) {
6356 zcomp_strm_free(zstrm);
64
- zstrm = NULL;
57
+ return -ENOMEM;
6558 }
66
- return zstrm;
59
+ return 0;
6760 }
6861
6962 bool zcomp_available_algorithm(const char *comp)
7063 {
71
- int i;
72
-
73
- i = __sysfs_match_string(backends, -1, comp);
74
- if (i >= 0)
75
- return true;
76
-
7764 /*
7865 * Crypto does not ignore a trailing new line symbol,
7966 * so make sure you don't supply a string containing
....@@ -89,9 +76,9 @@
8976 {
9077 bool known_algorithm = false;
9178 ssize_t sz = 0;
92
- int i = 0;
79
+ int i;
9380
94
- for (; backends[i]; i++) {
81
+ for (i = 0; i < ARRAY_SIZE(backends); i++) {
9582 if (!strcmp(comp, backends[i])) {
9683 known_algorithm = true;
9784 sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
....@@ -116,20 +103,13 @@
116103
117104 struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
118105 {
119
- struct zcomp_strm *zstrm;
120
-
121
- zstrm = *get_local_ptr(comp->stream);
122
- spin_lock(&zstrm->zcomp_lock);
123
- return zstrm;
106
+ local_lock(&comp->stream->lock);
107
+ return this_cpu_ptr(comp->stream);
124108 }
125109
126110 void zcomp_stream_put(struct zcomp *comp)
127111 {
128
- struct zcomp_strm *zstrm;
129
-
130
- zstrm = *this_cpu_ptr(comp->stream);
131
- spin_unlock(&zstrm->zcomp_lock);
132
- put_local_ptr(zstrm);
112
+ local_unlock(&comp->stream->lock);
133113 }
134114
135115 int zcomp_compress(struct zcomp_strm *zstrm,
....@@ -170,18 +150,15 @@
170150 {
171151 struct zcomp *comp = hlist_entry(node, struct zcomp, node);
172152 struct zcomp_strm *zstrm;
153
+ int ret;
173154
174
- if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
175
- return 0;
155
+ zstrm = per_cpu_ptr(comp->stream, cpu);
156
+ local_lock_init(&zstrm->lock);
176157
177
- zstrm = zcomp_strm_alloc(comp);
178
- if (IS_ERR_OR_NULL(zstrm)) {
158
+ ret = zcomp_strm_init(zstrm, comp);
159
+ if (ret)
179160 pr_err("Can't allocate a compression stream\n");
180
- return -ENOMEM;
181
- }
182
- spin_lock_init(&zstrm->zcomp_lock);
183
- *per_cpu_ptr(comp->stream, cpu) = zstrm;
184
- return 0;
161
+ return ret;
185162 }
186163
187164 int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node)
....@@ -189,10 +166,8 @@
189166 struct zcomp *comp = hlist_entry(node, struct zcomp, node);
190167 struct zcomp_strm *zstrm;
191168
192
- zstrm = *per_cpu_ptr(comp->stream, cpu);
193
- if (!IS_ERR_OR_NULL(zstrm))
194
- zcomp_strm_free(zstrm);
195
- *per_cpu_ptr(comp->stream, cpu) = NULL;
169
+ zstrm = per_cpu_ptr(comp->stream, cpu);
170
+ zcomp_strm_free(zstrm);
196171 return 0;
197172 }
198173
....@@ -200,7 +175,7 @@
200175 {
201176 int ret;
202177
203
- comp->stream = alloc_percpu(struct zcomp_strm *);
178
+ comp->stream = alloc_percpu(struct zcomp_strm);
204179 if (!comp->stream)
205180 return -ENOMEM;
206181
....@@ -234,6 +209,11 @@
234209 struct zcomp *comp;
235210 int error;
236211
212
+ /*
213
+ * Crypto API will execute /sbin/modprobe if the compression module
214
+ * is not loaded yet. We must do it here, otherwise we are about to
215
+ * call /sbin/modprobe under CPU hot-plug lock.
216
+ */
237217 if (!zcomp_available_algorithm(compress))
238218 return ERR_PTR(-EINVAL);
239219