diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2019-03-29 09:09:56 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2019-04-08 02:36:16 -0400 |
commit | 71052dcf4be70be4077817297dcde7b155e745f2 (patch) | |
tree | 4422a948fb51418bad38e1cf97763ee2a4d8683a | |
parent | 6a4d1b18ef00a7b182740b7b4d8a0fcd317368f8 (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.c | 125 |
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 | ||
32 | struct scomp_scratch { | ||
33 | spinlock_t lock; | ||
34 | void *src; | ||
35 | void *dst; | ||
36 | }; | ||
37 | |||
38 | static DEFINE_PER_CPU(struct scomp_scratch, scomp_scratch) = { | ||
39 | .lock = __SPIN_LOCK_UNLOCKED(scomp_scratch.lock), | ||
40 | }; | ||
41 | |||
32 | static const struct crypto_type crypto_scomp_type; | 42 | static const struct crypto_type crypto_scomp_type; |
33 | static void * __percpu *scomp_src_scratches; | ||
34 | static void * __percpu *scomp_dst_scratches; | ||
35 | static int scomp_scratch_users; | 43 | static int scomp_scratch_users; |
36 | static DEFINE_MUTEX(scomp_lock); | 44 | static 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 | ||
65 | static void crypto_scomp_free_scratches(void * __percpu *scratches) | 73 | static 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 | ||
78 | static void * __percpu *crypto_scomp_alloc_scratches(void) | 88 | static 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 | |||
98 | error: | ||
99 | crypto_scomp_free_scratches(scratches); | ||
100 | return NULL; | ||
101 | } | ||
102 | 95 | ||
103 | static 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 | ||
113 | static 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; |
108 | error: | ||
109 | crypto_scomp_free_scratches(); | ||
110 | return -ENOMEM; | ||
127 | } | 111 | } |
128 | 112 | ||
129 | static int crypto_scomp_init_tfm(struct crypto_tfm *tfm) | 113 | static 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 | } |
182 | out: | 164 | out: |
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 | ||