| | varnish-cache/bin/varnishd/storage/storage_persistent_subr.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2008-2011 Varnish Software AS |
2 |
|
* All rights reserved. |
3 |
|
* |
4 |
|
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> |
5 |
|
* |
6 |
|
* SPDX-License-Identifier: BSD-2-Clause |
7 |
|
* |
8 |
|
* Redistribution and use in source and binary forms, with or without |
9 |
|
* modification, are permitted provided that the following conditions |
10 |
|
* are met: |
11 |
|
* 1. Redistributions of source code must retain the above copyright |
12 |
|
* notice, this list of conditions and the following disclaimer. |
13 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
|
* notice, this list of conditions and the following disclaimer in the |
15 |
|
* documentation and/or other materials provided with the distribution. |
16 |
|
* |
17 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
18 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
21 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 |
|
* SUCH DAMAGE. |
28 |
|
* |
29 |
|
* Persistent storage method |
30 |
|
* |
31 |
|
* XXX: Before we start the client or maybe after it stops, we should give the |
32 |
|
* XXX: stevedores a chance to examine their storage for consistency. |
33 |
|
* |
34 |
|
* XXX: Do we ever free the LRU-lists ? |
35 |
|
*/ |
36 |
|
|
37 |
|
#include "config.h" |
38 |
|
|
39 |
|
#include "cache/cache_varnishd.h" |
40 |
|
|
41 |
|
#include <sys/mman.h> |
42 |
|
|
43 |
|
#include <stdio.h> |
44 |
|
#include <stdlib.h> |
45 |
|
|
46 |
|
#include "storage/storage.h" |
47 |
|
|
48 |
|
#include "vrnd.h" |
49 |
|
#include "vsha256.h" |
50 |
|
|
51 |
|
#include "storage/storage_persistent.h" |
52 |
|
|
53 |
|
static void smp_msync(const void *addr, size_t length); |
54 |
|
|
55 |
|
/*-------------------------------------------------------------------- |
56 |
|
* SIGNATURE functions |
57 |
|
* The signature is SHA256 over: |
58 |
|
* 1. The smp_sign struct up to but not including the length field. |
59 |
|
* 2. smp_sign->length bytes, starting after the smp_sign structure |
60 |
|
* 3. The smp-sign->length field. |
61 |
|
* The signature is stored after the byte-range from step 2. |
62 |
|
*/ |
63 |
|
|
64 |
|
/*-------------------------------------------------------------------- |
65 |
|
* Define a signature by location and identifier. |
66 |
|
*/ |
67 |
|
|
68 |
|
void |
69 |
23520 |
smp_def_sign(const struct smp_sc *sc, struct smp_signctx *ctx, |
70 |
|
uint64_t off, const char *id) |
71 |
|
{ |
72 |
|
|
73 |
23520 |
AZ(off & 7); /* Alignment */ |
74 |
23520 |
assert(strlen(id) < sizeof ctx->ss->ident); |
75 |
|
|
76 |
23520 |
memset(ctx, 0, sizeof *ctx); |
77 |
23520 |
ctx->ss = (void*)(sc->base + off); |
78 |
23520 |
ctx->unique = sc->unique; |
79 |
23520 |
ctx->id = id; |
80 |
23520 |
} |
81 |
|
|
82 |
|
/*-------------------------------------------------------------------- |
83 |
|
* Check that a signature is good, leave state ready for append |
84 |
|
*/ |
85 |
|
int |
86 |
25240 |
smp_chk_sign(struct smp_signctx *ctx) |
87 |
|
{ |
88 |
|
struct VSHA256Context cx; |
89 |
|
unsigned char sign[VSHA256_LEN]; |
90 |
25240 |
int r = 0; |
91 |
|
|
92 |
25240 |
if (strncmp(ctx->id, ctx->ss->ident, sizeof ctx->ss->ident)) |
93 |
680 |
r = 1; |
94 |
24560 |
else if (ctx->unique != ctx->ss->unique) |
95 |
0 |
r = 2; |
96 |
24560 |
else if (!ctx->ss->mapped) |
97 |
0 |
r = 3; |
98 |
|
else { |
99 |
24560 |
VSHA256_Init(&ctx->ctx); |
100 |
24560 |
VSHA256_Update(&ctx->ctx, ctx->ss, |
101 |
|
offsetof(struct smp_sign, length)); |
102 |
24560 |
VSHA256_Update(&ctx->ctx, SIGN_DATA(ctx), ctx->ss->length); |
103 |
24560 |
cx = ctx->ctx; |
104 |
24560 |
VSHA256_Update(&cx, &ctx->ss->length, sizeof(ctx->ss->length)); |
105 |
24560 |
VSHA256_Final(sign, &cx); |
106 |
24560 |
if (memcmp(sign, SIGN_END(ctx), sizeof sign)) |
107 |
0 |
r = 4; |
108 |
|
} |
109 |
25240 |
if (r) { |
110 |
1360 |
fprintf(stderr, "CHK(%p %s %p %s) = %d\n", |
111 |
680 |
ctx, ctx->id, ctx->ss, |
112 |
680 |
r > 1 ? ctx->ss->ident : "<invalid>", r); |
113 |
680 |
} |
114 |
25240 |
return (r); |
115 |
|
} |
116 |
|
|
117 |
|
/*-------------------------------------------------------------------- |
118 |
|
* Append data to a signature |
119 |
|
*/ |
120 |
|
static void |
121 |
35365 |
smp_append_sign(struct smp_signctx *ctx, const void *ptr, uint32_t len) |
122 |
|
{ |
123 |
|
struct VSHA256Context cx; |
124 |
|
unsigned char sign[VSHA256_LEN]; |
125 |
|
|
126 |
35365 |
if (len != 0) { |
127 |
15264 |
VSHA256_Update(&ctx->ctx, ptr, len); |
128 |
15264 |
ctx->ss->length += len; |
129 |
15264 |
} |
130 |
35365 |
cx = ctx->ctx; |
131 |
35365 |
VSHA256_Update(&cx, &ctx->ss->length, sizeof(ctx->ss->length)); |
132 |
35365 |
VSHA256_Final(sign, &cx); |
133 |
35365 |
memcpy(SIGN_END(ctx), sign, sizeof sign); |
134 |
35365 |
} |
135 |
|
|
136 |
|
/*-------------------------------------------------------------------- |
137 |
|
* Reset a signature to empty, prepare for appending. |
138 |
|
*/ |
139 |
|
|
140 |
|
void |
141 |
18703 |
smp_reset_sign(struct smp_signctx *ctx) |
142 |
|
{ |
143 |
|
|
144 |
18703 |
memset(ctx->ss, 0, sizeof *ctx->ss); |
145 |
18703 |
assert(strlen(ctx->id) < sizeof *ctx->ss); |
146 |
18703 |
strcpy(ctx->ss->ident, ctx->id); |
147 |
18703 |
ctx->ss->unique = ctx->unique; |
148 |
18703 |
ctx->ss->mapped = (uintptr_t)ctx->ss; |
149 |
18703 |
VSHA256_Init(&ctx->ctx); |
150 |
18703 |
VSHA256_Update(&ctx->ctx, ctx->ss, |
151 |
|
offsetof(struct smp_sign, length)); |
152 |
18703 |
smp_append_sign(ctx, NULL, 0); |
153 |
18703 |
} |
154 |
|
|
155 |
|
/*-------------------------------------------------------------------- |
156 |
|
* Force a write of a signature block to the backing store. |
157 |
|
*/ |
158 |
|
|
159 |
|
void |
160 |
18704 |
smp_sync_sign(const struct smp_signctx *ctx) |
161 |
|
{ |
162 |
18704 |
smp_msync(ctx->ss, SMP_SIGN_SPACE + ctx->ss->length); |
163 |
18704 |
} |
164 |
|
|
165 |
|
/*-------------------------------------------------------------------- |
166 |
|
* Create and force a new signature to backing store |
167 |
|
*/ |
168 |
|
|
169 |
|
static void |
170 |
2720 |
smp_new_sign(const struct smp_sc *sc, struct smp_signctx *ctx, |
171 |
|
uint64_t off, const char *id) |
172 |
|
{ |
173 |
2720 |
smp_def_sign(sc, ctx, off, id); |
174 |
2720 |
smp_reset_sign(ctx); |
175 |
2720 |
smp_sync_sign(ctx); |
176 |
2720 |
} |
177 |
|
|
178 |
|
/*-------------------------------------------------------------------- |
179 |
|
* Define a signature space by location, size and identifier |
180 |
|
*/ |
181 |
|
|
182 |
|
static void |
183 |
15520 |
smp_def_signspace(const struct smp_sc *sc, struct smp_signspace *spc, |
184 |
|
uint64_t off, uint64_t size, const char *id) |
185 |
|
{ |
186 |
15520 |
smp_def_sign(sc, &spc->ctx, off, id); |
187 |
15520 |
spc->start = SIGN_DATA(&spc->ctx); |
188 |
15520 |
spc->size = size - SMP_SIGN_SPACE; |
189 |
15520 |
} |
190 |
|
|
191 |
|
/*-------------------------------------------------------------------- |
192 |
|
* Check that a signspace's signature space is good, leave state ready |
193 |
|
* for append |
194 |
|
*/ |
195 |
|
|
196 |
|
int |
197 |
20080 |
smp_chk_signspace(struct smp_signspace *spc) |
198 |
|
{ |
199 |
20080 |
return (smp_chk_sign(&spc->ctx)); |
200 |
|
} |
201 |
|
|
202 |
|
/*-------------------------------------------------------------------- |
203 |
|
* Append data to a signature space |
204 |
|
*/ |
205 |
|
|
206 |
|
void |
207 |
15983 |
smp_append_signspace(struct smp_signspace *spc, uint32_t len) |
208 |
|
{ |
209 |
15983 |
assert(len <= SIGNSPACE_FREE(spc)); |
210 |
15983 |
smp_append_sign(&spc->ctx, SIGNSPACE_FRONT(spc), len); |
211 |
15983 |
} |
212 |
|
|
213 |
|
/*-------------------------------------------------------------------- |
214 |
|
* Reset a signature space to empty, prepare for appending. |
215 |
|
*/ |
216 |
|
|
217 |
|
void |
218 |
12144 |
smp_reset_signspace(struct smp_signspace *spc) |
219 |
|
{ |
220 |
12144 |
smp_reset_sign(&spc->ctx); |
221 |
12144 |
} |
222 |
|
|
223 |
|
/*-------------------------------------------------------------------- |
224 |
|
* Copy the contents of one signspace to another. Prepare for |
225 |
|
* appending. |
226 |
|
*/ |
227 |
|
|
228 |
|
void |
229 |
1520 |
smp_copy_signspace(struct smp_signspace *dst, const struct smp_signspace *src) |
230 |
|
{ |
231 |
1520 |
assert(SIGNSPACE_LEN(src) <= dst->size); |
232 |
1520 |
smp_reset_signspace(dst); |
233 |
1520 |
memcpy(SIGNSPACE_DATA(dst), SIGNSPACE_DATA(src), SIGNSPACE_LEN(src)); |
234 |
1520 |
smp_append_signspace(dst, SIGNSPACE_LEN(src)); |
235 |
1520 |
assert(SIGNSPACE_LEN(src) == SIGNSPACE_LEN(dst)); |
236 |
1520 |
} |
237 |
|
|
238 |
|
/*-------------------------------------------------------------------- |
239 |
|
* Create a new signature space and force the signature to backing store. |
240 |
|
*/ |
241 |
|
|
242 |
|
static void |
243 |
2720 |
smp_new_signspace(const struct smp_sc *sc, struct smp_signspace *spc, |
244 |
|
uint64_t off, uint64_t size, const char *id) |
245 |
|
{ |
246 |
2720 |
smp_new_sign(sc, &spc->ctx, off, id); |
247 |
2720 |
spc->start = SIGN_DATA(&spc->ctx); |
248 |
2720 |
spc->size = size - SMP_SIGN_SPACE; |
249 |
2720 |
} |
250 |
|
|
251 |
|
/*-------------------------------------------------------------------- |
252 |
|
* Force a write of a memory block (rounded to nearest pages) to |
253 |
|
* the backing store. |
254 |
|
*/ |
255 |
|
|
256 |
|
static void |
257 |
18704 |
smp_msync(const void *addr, size_t length) |
258 |
|
{ |
259 |
|
uintptr_t start, end, pagesize; |
260 |
|
|
261 |
18704 |
pagesize = getpagesize(); |
262 |
18704 |
assert(pagesize > 0 && PWR2(pagesize)); |
263 |
18704 |
start = RDN2((uintptr_t)addr, pagesize); |
264 |
18704 |
end = RUP2((uintptr_t)addr + length, pagesize); |
265 |
18704 |
assert(start < end); |
266 |
18704 |
AZ(msync((void *)start, end - start, MS_SYNC)); |
267 |
18704 |
} |
268 |
|
|
269 |
|
/*-------------------------------------------------------------------- |
270 |
|
* Initialize a Silo with a valid but empty structure. |
271 |
|
* |
272 |
|
* XXX: more intelligent sizing of things. |
273 |
|
*/ |
274 |
|
|
275 |
|
void |
276 |
680 |
smp_newsilo(struct smp_sc *sc) |
277 |
|
{ |
278 |
|
struct smp_ident *si; |
279 |
|
|
280 |
|
/* Choose a new random number */ |
281 |
680 |
AZ(VRND_RandomCrypto(&sc->unique, sizeof sc->unique)); |
282 |
|
|
283 |
680 |
smp_reset_sign(&sc->idn); |
284 |
680 |
si = sc->ident; |
285 |
|
|
286 |
680 |
memset(si, 0, sizeof *si); |
287 |
680 |
bstrcpy(si->ident, SMP_IDENT_STRING); |
288 |
680 |
si->byte_order = 0x12345678; |
289 |
680 |
si->size = sizeof *si; |
290 |
680 |
si->major_version = 2; |
291 |
680 |
si->unique = sc->unique; |
292 |
680 |
si->mediasize = sc->mediasize; |
293 |
680 |
si->granularity = sc->granularity; |
294 |
|
/* |
295 |
|
* Aim for cache-line-width |
296 |
|
*/ |
297 |
680 |
si->align = sizeof(void*) * 2; |
298 |
680 |
sc->align = si->align; |
299 |
|
|
300 |
680 |
si->stuff[SMP_BAN1_STUFF] = sc->granularity; |
301 |
680 |
si->stuff[SMP_BAN2_STUFF] = si->stuff[SMP_BAN1_STUFF] + 1024*1024; |
302 |
680 |
si->stuff[SMP_SEG1_STUFF] = si->stuff[SMP_BAN2_STUFF] + 1024*1024; |
303 |
680 |
si->stuff[SMP_SEG2_STUFF] = si->stuff[SMP_SEG1_STUFF] + 1024*1024; |
304 |
680 |
si->stuff[SMP_SPC_STUFF] = si->stuff[SMP_SEG2_STUFF] + 1024*1024; |
305 |
680 |
si->stuff[SMP_END_STUFF] = si->mediasize; |
306 |
680 |
assert(si->stuff[SMP_SPC_STUFF] < si->stuff[SMP_END_STUFF]); |
307 |
|
|
308 |
1360 |
smp_new_signspace(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF], |
309 |
680 |
smp_stuff_len(sc, SMP_BAN1_STUFF), "BAN 1"); |
310 |
1360 |
smp_new_signspace(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF], |
311 |
680 |
smp_stuff_len(sc, SMP_BAN2_STUFF), "BAN 2"); |
312 |
1360 |
smp_new_signspace(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF], |
313 |
680 |
smp_stuff_len(sc, SMP_SEG1_STUFF), "SEG 1"); |
314 |
1360 |
smp_new_signspace(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF], |
315 |
680 |
smp_stuff_len(sc, SMP_SEG2_STUFF), "SEG 2"); |
316 |
|
|
317 |
680 |
smp_append_sign(&sc->idn, si, sizeof *si); |
318 |
680 |
smp_sync_sign(&sc->idn); |
319 |
680 |
} |
320 |
|
|
321 |
|
/*-------------------------------------------------------------------- |
322 |
|
* Check if a silo is valid. |
323 |
|
*/ |
324 |
|
|
325 |
|
int |
326 |
4560 |
smp_valid_silo(struct smp_sc *sc) |
327 |
|
{ |
328 |
|
struct smp_ident *si; |
329 |
|
int i, j; |
330 |
|
|
331 |
4560 |
assert(strlen(SMP_IDENT_STRING) < sizeof si->ident); |
332 |
|
|
333 |
4560 |
i = smp_chk_sign(&sc->idn); |
334 |
4560 |
if (i) |
335 |
680 |
return (i); |
336 |
|
|
337 |
3880 |
si = sc->ident; |
338 |
3880 |
if (strcmp(si->ident, SMP_IDENT_STRING)) |
339 |
0 |
return (12); |
340 |
3880 |
if (si->byte_order != 0x12345678) |
341 |
0 |
return (13); |
342 |
3880 |
if (si->size != sizeof *si) |
343 |
0 |
return (14); |
344 |
3880 |
if (si->major_version != 2) |
345 |
0 |
return (15); |
346 |
3880 |
if (si->mediasize != sc->mediasize) |
347 |
0 |
return (17); |
348 |
3880 |
if (si->granularity != sc->granularity) |
349 |
0 |
return (18); |
350 |
3880 |
if (si->align < sizeof(void*)) |
351 |
0 |
return (19); |
352 |
3880 |
if (!PWR2(si->align)) |
353 |
0 |
return (20); |
354 |
3880 |
sc->align = si->align; |
355 |
3880 |
sc->unique = si->unique; |
356 |
|
|
357 |
|
/* XXX: Sanity check stuff[6] */ |
358 |
|
|
359 |
3880 |
assert(si->stuff[SMP_BAN1_STUFF] > sizeof *si + VSHA256_LEN); |
360 |
3880 |
assert(si->stuff[SMP_BAN2_STUFF] > si->stuff[SMP_BAN1_STUFF]); |
361 |
3880 |
assert(si->stuff[SMP_SEG1_STUFF] > si->stuff[SMP_BAN2_STUFF]); |
362 |
3880 |
assert(si->stuff[SMP_SEG2_STUFF] > si->stuff[SMP_SEG1_STUFF]); |
363 |
3880 |
assert(si->stuff[SMP_SPC_STUFF] > si->stuff[SMP_SEG2_STUFF]); |
364 |
3880 |
assert(si->stuff[SMP_END_STUFF] == sc->mediasize); |
365 |
|
|
366 |
3880 |
assert(smp_stuff_len(sc, SMP_SEG1_STUFF) > 65536); |
367 |
3880 |
assert(smp_stuff_len(sc, SMP_SEG1_STUFF) == |
368 |
|
smp_stuff_len(sc, SMP_SEG2_STUFF)); |
369 |
|
|
370 |
3880 |
assert(smp_stuff_len(sc, SMP_BAN1_STUFF) > 65536); |
371 |
3880 |
assert(smp_stuff_len(sc, SMP_BAN1_STUFF) == |
372 |
|
smp_stuff_len(sc, SMP_BAN2_STUFF)); |
373 |
|
|
374 |
7760 |
smp_def_signspace(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF], |
375 |
3880 |
smp_stuff_len(sc, SMP_BAN1_STUFF), "BAN 1"); |
376 |
7760 |
smp_def_signspace(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF], |
377 |
3880 |
smp_stuff_len(sc, SMP_BAN2_STUFF), "BAN 2"); |
378 |
7760 |
smp_def_signspace(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF], |
379 |
3880 |
smp_stuff_len(sc, SMP_SEG1_STUFF), "SEG 1"); |
380 |
7760 |
smp_def_signspace(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF], |
381 |
3880 |
smp_stuff_len(sc, SMP_SEG2_STUFF), "SEG 2"); |
382 |
|
|
383 |
|
/* We must have one valid BAN table */ |
384 |
3880 |
i = smp_chk_signspace(&sc->ban1); |
385 |
3880 |
j = smp_chk_signspace(&sc->ban2); |
386 |
3880 |
if (i && j) |
387 |
0 |
return (100 + i * 10 + j); |
388 |
|
|
389 |
|
/* We must have one valid SEG table */ |
390 |
3880 |
i = smp_chk_signspace(&sc->seg1); |
391 |
3880 |
j = smp_chk_signspace(&sc->seg2); |
392 |
3880 |
if (i && j) |
393 |
0 |
return (200 + i * 10 + j); |
394 |
3880 |
return (0); |
395 |
4560 |
} |