| | 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 |
35359 |
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 |
35359 |
if (len != 0) { |
| 127 |
15261 |
VSHA256_Update(&ctx->ctx, ptr, len); |
| 128 |
15261 |
ctx->ss->length += len; |
| 129 |
15261 |
} |
| 130 |
35359 |
cx = ctx->ctx; |
| 131 |
35359 |
VSHA256_Update(&cx, &ctx->ss->length, sizeof(ctx->ss->length)); |
| 132 |
35359 |
VSHA256_Final(sign, &cx); |
| 133 |
35359 |
memcpy(SIGN_END(ctx), sign, sizeof sign); |
| 134 |
35359 |
} |
| 135 |
|
|
| 136 |
|
/*-------------------------------------------------------------------- |
| 137 |
|
* Reset a signature to empty, prepare for appending. |
| 138 |
|
*/ |
| 139 |
|
|
| 140 |
|
void |
| 141 |
18699 |
smp_reset_sign(struct smp_signctx *ctx) |
| 142 |
|
{ |
| 143 |
|
|
| 144 |
18699 |
memset(ctx->ss, 0, sizeof *ctx->ss); |
| 145 |
18699 |
assert(strlen(ctx->id) < sizeof *ctx->ss); |
| 146 |
18699 |
strcpy(ctx->ss->ident, ctx->id); |
| 147 |
18699 |
ctx->ss->unique = ctx->unique; |
| 148 |
18699 |
ctx->ss->mapped = (uintptr_t)ctx->ss; |
| 149 |
18699 |
VSHA256_Init(&ctx->ctx); |
| 150 |
18699 |
VSHA256_Update(&ctx->ctx, ctx->ss, |
| 151 |
|
offsetof(struct smp_sign, length)); |
| 152 |
18699 |
smp_append_sign(ctx, NULL, 0); |
| 153 |
18699 |
} |
| 154 |
|
|
| 155 |
|
/*-------------------------------------------------------------------- |
| 156 |
|
* Force a write of a signature block to the backing store. |
| 157 |
|
*/ |
| 158 |
|
|
| 159 |
|
void |
| 160 |
18701 |
smp_sync_sign(const struct smp_signctx *ctx) |
| 161 |
|
{ |
| 162 |
18701 |
smp_msync(ctx->ss, SMP_SIGN_SPACE + ctx->ss->length); |
| 163 |
18701 |
} |
| 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 |
15980 |
smp_append_signspace(struct smp_signspace *spc, uint32_t len) |
| 208 |
|
{ |
| 209 |
15980 |
assert(len <= SIGNSPACE_FREE(spc)); |
| 210 |
15980 |
smp_append_sign(&spc->ctx, SIGNSPACE_FRONT(spc), len); |
| 211 |
15980 |
} |
| 212 |
|
|
| 213 |
|
/*-------------------------------------------------------------------- |
| 214 |
|
* Reset a signature space to empty, prepare for appending. |
| 215 |
|
*/ |
| 216 |
|
|
| 217 |
|
void |
| 218 |
12141 |
smp_reset_signspace(struct smp_signspace *spc) |
| 219 |
|
{ |
| 220 |
12141 |
smp_reset_sign(&spc->ctx); |
| 221 |
12141 |
} |
| 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 |
18702 |
smp_msync(const void *addr, size_t length) |
| 258 |
|
{ |
| 259 |
|
uintptr_t start, end, pagesize; |
| 260 |
|
|
| 261 |
18702 |
pagesize = getpagesize(); |
| 262 |
18702 |
assert(pagesize > 0 && PWR2(pagesize)); |
| 263 |
18702 |
start = RDN2((uintptr_t)addr, pagesize); |
| 264 |
18702 |
end = RUP2((uintptr_t)addr + length, pagesize); |
| 265 |
18702 |
assert(start < end); |
| 266 |
18702 |
AZ(msync((void *)start, end - start, MS_SYNC)); |
| 267 |
18702 |
} |
| 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 |
} |