| | 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 |
|
#include "common/heritage.h" |
41 |
|
|
42 |
|
#include <sys/mman.h> |
43 |
|
|
44 |
|
#include <stdio.h> |
45 |
|
#include <stdlib.h> |
46 |
|
|
47 |
|
#include "storage/storage.h" |
48 |
|
|
49 |
|
#include "vrnd.h" |
50 |
|
#include "vsha256.h" |
51 |
|
|
52 |
|
#include "storage/storage_persistent.h" |
53 |
|
|
54 |
|
static void smp_msync(const void *addr, size_t length); |
55 |
|
|
56 |
|
/*-------------------------------------------------------------------- |
57 |
|
* SIGNATURE functions |
58 |
|
* The signature is SHA256 over: |
59 |
|
* 1. The smp_sign struct up to but not including the length field. |
60 |
|
* 2. smp_sign->length bytes, starting after the smp_sign structure |
61 |
|
* 3. The smp-sign->length field. |
62 |
|
* The signature is stored after the byte-range from step 2. |
63 |
|
*/ |
64 |
|
|
65 |
|
/*-------------------------------------------------------------------- |
66 |
|
* Define a signature by location and identifier. |
67 |
|
*/ |
68 |
|
|
69 |
|
void |
70 |
14700 |
smp_def_sign(const struct smp_sc *sc, struct smp_signctx *ctx, |
71 |
|
uint64_t off, const char *id) |
72 |
|
{ |
73 |
|
|
74 |
14700 |
AZ(off & 7); /* Alignment */ |
75 |
14700 |
assert(strlen(id) < sizeof ctx->ss->ident); |
76 |
|
|
77 |
14700 |
memset(ctx, 0, sizeof *ctx); |
78 |
14700 |
ctx->ss = (void*)(sc->base + off); |
79 |
14700 |
ctx->unique = sc->unique; |
80 |
14700 |
ctx->id = id; |
81 |
14700 |
} |
82 |
|
|
83 |
|
/*-------------------------------------------------------------------- |
84 |
|
* Check that a signature is good, leave state ready for append |
85 |
|
*/ |
86 |
|
int |
87 |
15775 |
smp_chk_sign(struct smp_signctx *ctx) |
88 |
|
{ |
89 |
|
struct VSHA256Context cx; |
90 |
|
unsigned char sign[VSHA256_LEN]; |
91 |
15775 |
int r = 0; |
92 |
|
|
93 |
15775 |
if (strncmp(ctx->id, ctx->ss->ident, sizeof ctx->ss->ident)) |
94 |
425 |
r = 1; |
95 |
15350 |
else if (ctx->unique != ctx->ss->unique) |
96 |
0 |
r = 2; |
97 |
15350 |
else if (!ctx->ss->mapped) |
98 |
0 |
r = 3; |
99 |
|
else { |
100 |
15350 |
VSHA256_Init(&ctx->ctx); |
101 |
15350 |
VSHA256_Update(&ctx->ctx, ctx->ss, |
102 |
|
offsetof(struct smp_sign, length)); |
103 |
15350 |
VSHA256_Update(&ctx->ctx, SIGN_DATA(ctx), ctx->ss->length); |
104 |
15350 |
cx = ctx->ctx; |
105 |
15350 |
VSHA256_Update(&cx, &ctx->ss->length, sizeof(ctx->ss->length)); |
106 |
15350 |
VSHA256_Final(sign, &cx); |
107 |
15350 |
if (memcmp(sign, SIGN_END(ctx), sizeof sign)) |
108 |
0 |
r = 4; |
109 |
|
} |
110 |
15775 |
if (r) { |
111 |
850 |
fprintf(stderr, "CHK(%p %s %p %s) = %d\n", |
112 |
425 |
ctx, ctx->id, ctx->ss, |
113 |
425 |
r > 1 ? ctx->ss->ident : "<invalid>", r); |
114 |
425 |
} |
115 |
15775 |
return (r); |
116 |
|
} |
117 |
|
|
118 |
|
/*-------------------------------------------------------------------- |
119 |
|
* Append data to a signature |
120 |
|
*/ |
121 |
|
static void |
122 |
22114 |
smp_append_sign(struct smp_signctx *ctx, const void *ptr, uint32_t len) |
123 |
|
{ |
124 |
|
struct VSHA256Context cx; |
125 |
|
unsigned char sign[VSHA256_LEN]; |
126 |
|
|
127 |
22114 |
if (len != 0) { |
128 |
9546 |
VSHA256_Update(&ctx->ctx, ptr, len); |
129 |
9546 |
ctx->ss->length += len; |
130 |
9546 |
} |
131 |
22114 |
cx = ctx->ctx; |
132 |
22114 |
VSHA256_Update(&cx, &ctx->ss->length, sizeof(ctx->ss->length)); |
133 |
22114 |
VSHA256_Final(sign, &cx); |
134 |
22114 |
memcpy(SIGN_END(ctx), sign, sizeof sign); |
135 |
22114 |
} |
136 |
|
|
137 |
|
/*-------------------------------------------------------------------- |
138 |
|
* Reset a signature to empty, prepare for appending. |
139 |
|
*/ |
140 |
|
|
141 |
|
void |
142 |
11694 |
smp_reset_sign(struct smp_signctx *ctx) |
143 |
|
{ |
144 |
|
|
145 |
11694 |
memset(ctx->ss, 0, sizeof *ctx->ss); |
146 |
11694 |
assert(strlen(ctx->id) < sizeof *ctx->ss); |
147 |
11694 |
strcpy(ctx->ss->ident, ctx->id); |
148 |
11694 |
ctx->ss->unique = ctx->unique; |
149 |
11694 |
ctx->ss->mapped = (uintptr_t)ctx->ss; |
150 |
11694 |
VSHA256_Init(&ctx->ctx); |
151 |
11694 |
VSHA256_Update(&ctx->ctx, ctx->ss, |
152 |
|
offsetof(struct smp_sign, length)); |
153 |
11694 |
smp_append_sign(ctx, NULL, 0); |
154 |
11694 |
} |
155 |
|
|
156 |
|
/*-------------------------------------------------------------------- |
157 |
|
* Force a write of a signature block to the backing store. |
158 |
|
*/ |
159 |
|
|
160 |
|
void |
161 |
11696 |
smp_sync_sign(const struct smp_signctx *ctx) |
162 |
|
{ |
163 |
11696 |
smp_msync(ctx->ss, SMP_SIGN_SPACE + ctx->ss->length); |
164 |
11696 |
} |
165 |
|
|
166 |
|
/*-------------------------------------------------------------------- |
167 |
|
* Create and force a new signature to backing store |
168 |
|
*/ |
169 |
|
|
170 |
|
static void |
171 |
1700 |
smp_new_sign(const struct smp_sc *sc, struct smp_signctx *ctx, |
172 |
|
uint64_t off, const char *id) |
173 |
|
{ |
174 |
1700 |
smp_def_sign(sc, ctx, off, id); |
175 |
1700 |
smp_reset_sign(ctx); |
176 |
1700 |
smp_sync_sign(ctx); |
177 |
1700 |
} |
178 |
|
|
179 |
|
/*-------------------------------------------------------------------- |
180 |
|
* Define a signature space by location, size and identifier |
181 |
|
*/ |
182 |
|
|
183 |
|
static void |
184 |
9700 |
smp_def_signspace(const struct smp_sc *sc, struct smp_signspace *spc, |
185 |
|
uint64_t off, uint64_t size, const char *id) |
186 |
|
{ |
187 |
9700 |
smp_def_sign(sc, &spc->ctx, off, id); |
188 |
9700 |
spc->start = SIGN_DATA(&spc->ctx); |
189 |
9700 |
spc->size = size - SMP_SIGN_SPACE; |
190 |
9700 |
} |
191 |
|
|
192 |
|
/*-------------------------------------------------------------------- |
193 |
|
* Check that a signspace's signature space is good, leave state ready |
194 |
|
* for append |
195 |
|
*/ |
196 |
|
|
197 |
|
int |
198 |
12550 |
smp_chk_signspace(struct smp_signspace *spc) |
199 |
|
{ |
200 |
12550 |
return (smp_chk_sign(&spc->ctx)); |
201 |
|
} |
202 |
|
|
203 |
|
/*-------------------------------------------------------------------- |
204 |
|
* Append data to a signature space |
205 |
|
*/ |
206 |
|
|
207 |
|
void |
208 |
9995 |
smp_append_signspace(struct smp_signspace *spc, uint32_t len) |
209 |
|
{ |
210 |
9995 |
assert(len <= SIGNSPACE_FREE(spc)); |
211 |
9995 |
smp_append_sign(&spc->ctx, SIGNSPACE_FRONT(spc), len); |
212 |
9995 |
} |
213 |
|
|
214 |
|
/*-------------------------------------------------------------------- |
215 |
|
* Reset a signature space to empty, prepare for appending. |
216 |
|
*/ |
217 |
|
|
218 |
|
void |
219 |
7596 |
smp_reset_signspace(struct smp_signspace *spc) |
220 |
|
{ |
221 |
7596 |
smp_reset_sign(&spc->ctx); |
222 |
7596 |
} |
223 |
|
|
224 |
|
/*-------------------------------------------------------------------- |
225 |
|
* Copy the contents of one signspace to another. Prepare for |
226 |
|
* appending. |
227 |
|
*/ |
228 |
|
|
229 |
|
void |
230 |
950 |
smp_copy_signspace(struct smp_signspace *dst, const struct smp_signspace *src) |
231 |
|
{ |
232 |
950 |
assert(SIGNSPACE_LEN(src) <= dst->size); |
233 |
950 |
smp_reset_signspace(dst); |
234 |
950 |
memcpy(SIGNSPACE_DATA(dst), SIGNSPACE_DATA(src), SIGNSPACE_LEN(src)); |
235 |
950 |
smp_append_signspace(dst, SIGNSPACE_LEN(src)); |
236 |
950 |
assert(SIGNSPACE_LEN(src) == SIGNSPACE_LEN(dst)); |
237 |
950 |
} |
238 |
|
|
239 |
|
/*-------------------------------------------------------------------- |
240 |
|
* Create a new signature space and force the signature to backing store. |
241 |
|
*/ |
242 |
|
|
243 |
|
static void |
244 |
1700 |
smp_new_signspace(const struct smp_sc *sc, struct smp_signspace *spc, |
245 |
|
uint64_t off, uint64_t size, const char *id) |
246 |
|
{ |
247 |
1700 |
smp_new_sign(sc, &spc->ctx, off, id); |
248 |
1700 |
spc->start = SIGN_DATA(&spc->ctx); |
249 |
1700 |
spc->size = size - SMP_SIGN_SPACE; |
250 |
1700 |
} |
251 |
|
|
252 |
|
/*-------------------------------------------------------------------- |
253 |
|
* Force a write of a memory block (rounded to nearest pages) to |
254 |
|
* the backing store. |
255 |
|
*/ |
256 |
|
|
257 |
|
static void |
258 |
11696 |
smp_msync(const void *addr, size_t length) |
259 |
|
{ |
260 |
|
uintptr_t start, end, pagesize; |
261 |
|
|
262 |
11696 |
pagesize = getpagesize(); |
263 |
11696 |
assert(pagesize > 0 && PWR2(pagesize)); |
264 |
11696 |
start = RDN2((uintptr_t)addr, pagesize); |
265 |
11696 |
end = RUP2((uintptr_t)addr + length, pagesize); |
266 |
11696 |
assert(start < end); |
267 |
11696 |
AZ(msync((void *)start, end - start, MS_SYNC)); |
268 |
11696 |
} |
269 |
|
|
270 |
|
/*-------------------------------------------------------------------- |
271 |
|
* Initialize a Silo with a valid but empty structure. |
272 |
|
* |
273 |
|
* XXX: more intelligent sizing of things. |
274 |
|
*/ |
275 |
|
|
276 |
|
void |
277 |
425 |
smp_newsilo(struct smp_sc *sc) |
278 |
|
{ |
279 |
|
struct smp_ident *si; |
280 |
|
|
281 |
|
/* Choose a new random number */ |
282 |
425 |
AZ(VRND_RandomCrypto(&sc->unique, sizeof sc->unique)); |
283 |
|
|
284 |
425 |
smp_reset_sign(&sc->idn); |
285 |
425 |
si = sc->ident; |
286 |
|
|
287 |
425 |
memset(si, 0, sizeof *si); |
288 |
425 |
bstrcpy(si->ident, SMP_IDENT_STRING); |
289 |
425 |
si->byte_order = 0x12345678; |
290 |
425 |
si->size = sizeof *si; |
291 |
425 |
si->major_version = 2; |
292 |
425 |
si->unique = sc->unique; |
293 |
425 |
si->mediasize = sc->mediasize; |
294 |
425 |
si->granularity = sc->granularity; |
295 |
|
/* |
296 |
|
* Aim for cache-line-width |
297 |
|
*/ |
298 |
425 |
si->align = sizeof(void*) * 2; |
299 |
425 |
sc->align = si->align; |
300 |
|
|
301 |
425 |
si->stuff[SMP_BAN1_STUFF] = sc->granularity; |
302 |
425 |
si->stuff[SMP_BAN2_STUFF] = si->stuff[SMP_BAN1_STUFF] + 1024*1024; |
303 |
425 |
si->stuff[SMP_SEG1_STUFF] = si->stuff[SMP_BAN2_STUFF] + 1024*1024; |
304 |
425 |
si->stuff[SMP_SEG2_STUFF] = si->stuff[SMP_SEG1_STUFF] + 1024*1024; |
305 |
425 |
si->stuff[SMP_SPC_STUFF] = si->stuff[SMP_SEG2_STUFF] + 1024*1024; |
306 |
425 |
si->stuff[SMP_END_STUFF] = si->mediasize; |
307 |
425 |
assert(si->stuff[SMP_SPC_STUFF] < si->stuff[SMP_END_STUFF]); |
308 |
|
|
309 |
850 |
smp_new_signspace(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF], |
310 |
425 |
smp_stuff_len(sc, SMP_BAN1_STUFF), "BAN 1"); |
311 |
850 |
smp_new_signspace(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF], |
312 |
425 |
smp_stuff_len(sc, SMP_BAN2_STUFF), "BAN 2"); |
313 |
850 |
smp_new_signspace(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF], |
314 |
425 |
smp_stuff_len(sc, SMP_SEG1_STUFF), "SEG 1"); |
315 |
850 |
smp_new_signspace(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF], |
316 |
425 |
smp_stuff_len(sc, SMP_SEG2_STUFF), "SEG 2"); |
317 |
|
|
318 |
425 |
smp_append_sign(&sc->idn, si, sizeof *si); |
319 |
425 |
smp_sync_sign(&sc->idn); |
320 |
425 |
} |
321 |
|
|
322 |
|
/*-------------------------------------------------------------------- |
323 |
|
* Check if a silo is valid. |
324 |
|
*/ |
325 |
|
|
326 |
|
int |
327 |
2850 |
smp_valid_silo(struct smp_sc *sc) |
328 |
|
{ |
329 |
|
struct smp_ident *si; |
330 |
|
int i, j; |
331 |
|
|
332 |
2850 |
assert(strlen(SMP_IDENT_STRING) < sizeof si->ident); |
333 |
|
|
334 |
2850 |
i = smp_chk_sign(&sc->idn); |
335 |
2850 |
if (i) |
336 |
425 |
return (i); |
337 |
|
|
338 |
2425 |
si = sc->ident; |
339 |
2425 |
if (strcmp(si->ident, SMP_IDENT_STRING)) |
340 |
0 |
return (12); |
341 |
2425 |
if (si->byte_order != 0x12345678) |
342 |
0 |
return (13); |
343 |
2425 |
if (si->size != sizeof *si) |
344 |
0 |
return (14); |
345 |
2425 |
if (si->major_version != 2) |
346 |
0 |
return (15); |
347 |
2425 |
if (si->mediasize != sc->mediasize) |
348 |
0 |
return (17); |
349 |
2425 |
if (si->granularity != sc->granularity) |
350 |
0 |
return (18); |
351 |
2425 |
if (si->align < sizeof(void*)) |
352 |
0 |
return (19); |
353 |
2425 |
if (!PWR2(si->align)) |
354 |
0 |
return (20); |
355 |
2425 |
sc->align = si->align; |
356 |
2425 |
sc->unique = si->unique; |
357 |
|
|
358 |
|
/* XXX: Sanity check stuff[6] */ |
359 |
|
|
360 |
2425 |
assert(si->stuff[SMP_BAN1_STUFF] > sizeof *si + VSHA256_LEN); |
361 |
2425 |
assert(si->stuff[SMP_BAN2_STUFF] > si->stuff[SMP_BAN1_STUFF]); |
362 |
2425 |
assert(si->stuff[SMP_SEG1_STUFF] > si->stuff[SMP_BAN2_STUFF]); |
363 |
2425 |
assert(si->stuff[SMP_SEG2_STUFF] > si->stuff[SMP_SEG1_STUFF]); |
364 |
2425 |
assert(si->stuff[SMP_SPC_STUFF] > si->stuff[SMP_SEG2_STUFF]); |
365 |
2425 |
assert(si->stuff[SMP_END_STUFF] == sc->mediasize); |
366 |
|
|
367 |
2425 |
assert(smp_stuff_len(sc, SMP_SEG1_STUFF) > 65536); |
368 |
2425 |
assert(smp_stuff_len(sc, SMP_SEG1_STUFF) == |
369 |
|
smp_stuff_len(sc, SMP_SEG2_STUFF)); |
370 |
|
|
371 |
2425 |
assert(smp_stuff_len(sc, SMP_BAN1_STUFF) > 65536); |
372 |
2425 |
assert(smp_stuff_len(sc, SMP_BAN1_STUFF) == |
373 |
|
smp_stuff_len(sc, SMP_BAN2_STUFF)); |
374 |
|
|
375 |
4850 |
smp_def_signspace(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF], |
376 |
2425 |
smp_stuff_len(sc, SMP_BAN1_STUFF), "BAN 1"); |
377 |
4850 |
smp_def_signspace(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF], |
378 |
2425 |
smp_stuff_len(sc, SMP_BAN2_STUFF), "BAN 2"); |
379 |
4850 |
smp_def_signspace(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF], |
380 |
2425 |
smp_stuff_len(sc, SMP_SEG1_STUFF), "SEG 1"); |
381 |
4850 |
smp_def_signspace(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF], |
382 |
2425 |
smp_stuff_len(sc, SMP_SEG2_STUFF), "SEG 2"); |
383 |
|
|
384 |
|
/* We must have one valid BAN table */ |
385 |
2425 |
i = smp_chk_signspace(&sc->ban1); |
386 |
2425 |
j = smp_chk_signspace(&sc->ban2); |
387 |
2425 |
if (i && j) |
388 |
0 |
return (100 + i * 10 + j); |
389 |
|
|
390 |
|
/* We must have one valid SEG table */ |
391 |
2425 |
i = smp_chk_signspace(&sc->seg1); |
392 |
2425 |
j = smp_chk_signspace(&sc->seg2); |
393 |
2425 |
if (i && j) |
394 |
0 |
return (200 + i * 10 + j); |
395 |
2425 |
return (0); |
396 |
2850 |
} |