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