summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2019-03-29 09:09:56 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-04-08 02:36:16 -0400
commit71052dcf4be70be4077817297dcde7b155e745f2 (patch)
tree4422a948fb51418bad38e1cf97763ee2a4d8683a
parent6a4d1b18ef00a7b182740b7b4d8a0fcd317368f8 (diff)
crypto: scompress - Use per-CPU struct instead multiple variables
Two per-CPU variables are allocated as pointer to per-CPU memory which then are used as scratch buffers. We could be smart about this and use instead a per-CPU struct which contains the pointers already and then we need to allocate just the scratch buffers. Add a lock to the struct. By doing so we can avoid the get_cpu() statement and gain lockdep coverage (if enabled) to ensure that the lock is always acquired in the right context. On non-preemptible kernels the lock vanishes. It is okay to use raw_cpu_ptr() in order to get a pointer to the struct since it is protected by the spinlock. The diffstat of this is negative and according to size scompress.o: text data bss dec hex filename 1847 160 24 2031 7ef dbg_before.o 1754 232 4 1990 7c6 dbg_after.o 1799 64 24 1887 75f no_dbg-before.o 1703 88 4 1795 703 no_dbg-after.o The overall size increase difference is also negative. The increase in the data section is only four bytes without lockdep. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/scompress.c125
1 files changed, 54 insertions, 71 deletions
diff --git a/crypto/scompress.c b/crypto/scompress.c
index aea1a8e5d195..da31f6fe1f83 100644
--- a/crypto/scompress.c
+++ b/crypto/scompress.c
@@ -29,9 +29,17 @@
29#include <crypto/internal/scompress.h> 29#include <crypto/internal/scompress.h>
30#include "internal.h" 30#include "internal.h"
31 31
32struct scomp_scratch {
33 spinlock_t lock;
34 void *src;
35 void *dst;
36};
37
38static DEFINE_PER_CPU(struct scomp_scratch, scomp_scratch) = {
39 .lock = __SPIN_LOCK_UNLOCKED(scomp_scratch.lock),
40};
41
32static const struct crypto_type crypto_scomp_type; 42static const struct crypto_type crypto_scomp_type;
33static void * __percpu *scomp_src_scratches;
34static void * __percpu *scomp_dst_scratches;
35static int scomp_scratch_users; 43static int scomp_scratch_users;
36static DEFINE_MUTEX(scomp_lock); 44static DEFINE_MUTEX(scomp_lock);
37 45
@@ -62,76 +70,53 @@ static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
62 seq_puts(m, "type : scomp\n"); 70 seq_puts(m, "type : scomp\n");
63} 71}
64 72
65static void crypto_scomp_free_scratches(void * __percpu *scratches) 73static void crypto_scomp_free_scratches(void)
66{ 74{
75 struct scomp_scratch *scratch;
67 int i; 76 int i;
68 77
69 if (!scratches) 78 for_each_possible_cpu(i) {
70 return; 79 scratch = raw_cpu_ptr(&scomp_scratch);
71
72 for_each_possible_cpu(i)
73 vfree(*per_cpu_ptr(scratches, i));
74 80
75 free_percpu(scratches); 81 vfree(scratch->src);
82 vfree(scratch->dst);
83 scratch->src = NULL;
84 scratch->dst = NULL;
85 }
76} 86}
77 87
78static void * __percpu *crypto_scomp_alloc_scratches(void) 88static int crypto_scomp_alloc_scratches(void)
79{ 89{
80 void * __percpu *scratches; 90 struct scomp_scratch *scratch;
81 int i; 91 int i;
82 92
83 scratches = alloc_percpu(void *);
84 if (!scratches)
85 return NULL;
86
87 for_each_possible_cpu(i) { 93 for_each_possible_cpu(i) {
88 void *scratch; 94 void *mem;
89
90 scratch = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
91 if (!scratch)
92 goto error;
93 *per_cpu_ptr(scratches, i) = scratch;
94 }
95
96 return scratches;
97
98error:
99 crypto_scomp_free_scratches(scratches);
100 return NULL;
101}
102 95
103static void crypto_scomp_free_all_scratches(void) 96 scratch = raw_cpu_ptr(&scomp_scratch);
104{
105 if (!--scomp_scratch_users) {
106 crypto_scomp_free_scratches(scomp_src_scratches);
107 crypto_scomp_free_scratches(scomp_dst_scratches);
108 scomp_src_scratches = NULL;
109 scomp_dst_scratches = NULL;
110 }
111}
112 97
113static int crypto_scomp_alloc_all_scratches(void) 98 mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
114{ 99 if (!mem)
115 if (!scomp_scratch_users++) { 100 goto error;
116 scomp_src_scratches = crypto_scomp_alloc_scratches(); 101 scratch->src = mem;
117 if (!scomp_src_scratches) 102 mem = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
118 return -ENOMEM; 103 if (!mem)
119 scomp_dst_scratches = crypto_scomp_alloc_scratches(); 104 goto error;
120 if (!scomp_dst_scratches) { 105 scratch->dst = mem;
121 crypto_scomp_free_scratches(scomp_src_scratches);
122 scomp_src_scratches = NULL;
123 return -ENOMEM;
124 }
125 } 106 }
126 return 0; 107 return 0;
108error:
109 crypto_scomp_free_scratches();
110 return -ENOMEM;
127} 111}
128 112
129static int crypto_scomp_init_tfm(struct crypto_tfm *tfm) 113static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
130{ 114{
131 int ret; 115 int ret = 0;
132 116
133 mutex_lock(&scomp_lock); 117 mutex_lock(&scomp_lock);
134 ret = crypto_scomp_alloc_all_scratches(); 118 if (!scomp_scratch_users++)
119 ret = crypto_scomp_alloc_scratches();
135 mutex_unlock(&scomp_lock); 120 mutex_unlock(&scomp_lock);
136 121
137 return ret; 122 return ret;
@@ -143,31 +128,28 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
143 void **tfm_ctx = acomp_tfm_ctx(tfm); 128 void **tfm_ctx = acomp_tfm_ctx(tfm);
144 struct crypto_scomp *scomp = *tfm_ctx; 129 struct crypto_scomp *scomp = *tfm_ctx;
145 void **ctx = acomp_request_ctx(req); 130 void **ctx = acomp_request_ctx(req);
146 const int cpu = get_cpu(); 131 struct scomp_scratch *scratch;
147 u8 *scratch_src = *per_cpu_ptr(scomp_src_scratches, cpu);
148 u8 *scratch_dst = *per_cpu_ptr(scomp_dst_scratches, cpu);
149 int ret; 132 int ret;
150 133
151 if (!req->src || !req->slen || req->slen > SCOMP_SCRATCH_SIZE) { 134 if (!req->src || !req->slen || req->slen > SCOMP_SCRATCH_SIZE)
152 ret = -EINVAL; 135 return -EINVAL;
153 goto out;
154 }
155 136
156 if (req->dst && !req->dlen) { 137 if (req->dst && !req->dlen)
157 ret = -EINVAL; 138 return -EINVAL;
158 goto out;
159 }
160 139
161 if (!req->dlen || req->dlen > SCOMP_SCRATCH_SIZE) 140 if (!req->dlen || req->dlen > SCOMP_SCRATCH_SIZE)
162 req->dlen = SCOMP_SCRATCH_SIZE; 141 req->dlen = SCOMP_SCRATCH_SIZE;
163 142
164 scatterwalk_map_and_copy(scratch_src, req->src, 0, req->slen, 0); 143 scratch = raw_cpu_ptr(&scomp_scratch);
144 spin_lock(&scratch->lock);
145
146 scatterwalk_map_and_copy(scratch->src, req->src, 0, req->slen, 0);
165 if (dir) 147 if (dir)
166 ret = crypto_scomp_compress(scomp, scratch_src, req->slen, 148 ret = crypto_scomp_compress(scomp, scratch->src, req->slen,
167 scratch_dst, &req->dlen, *ctx); 149 scratch->dst, &req->dlen, *ctx);
168 else 150 else
169 ret = crypto_scomp_decompress(scomp, scratch_src, req->slen, 151 ret = crypto_scomp_decompress(scomp, scratch->src, req->slen,
170 scratch_dst, &req->dlen, *ctx); 152 scratch->dst, &req->dlen, *ctx);
171 if (!ret) { 153 if (!ret) {
172 if (!req->dst) { 154 if (!req->dst) {
173 req->dst = sgl_alloc(req->dlen, GFP_ATOMIC, NULL); 155 req->dst = sgl_alloc(req->dlen, GFP_ATOMIC, NULL);
@@ -176,11 +158,11 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
176 goto out; 158 goto out;
177 } 159 }
178 } 160 }
179 scatterwalk_map_and_copy(scratch_dst, req->dst, 0, req->dlen, 161 scatterwalk_map_and_copy(scratch->dst, req->dst, 0, req->dlen,
180 1); 162 1);
181 } 163 }
182out: 164out:
183 put_cpu(); 165 spin_unlock(&scratch->lock);
184 return ret; 166 return ret;
185} 167}
186 168
@@ -201,7 +183,8 @@ static void crypto_exit_scomp_ops_async(struct crypto_tfm *tfm)
201 crypto_free_scomp(*ctx); 183 crypto_free_scomp(*ctx);
202 184
203 mutex_lock(&scomp_lock); 185 mutex_lock(&scomp_lock);
204 crypto_scomp_free_all_scratches(); 186 if (!--scomp_scratch_users)
187 crypto_scomp_free_scratches();
205 mutex_unlock(&scomp_lock); 188 mutex_unlock(&scomp_lock);
206} 189}
207 190