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