varnish-cache/bin/varnishd/storage/mgt_storage_persistent.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 <errno.h>
44
#include <stdio.h>
45
#include <stdlib.h>
46
47
#include "storage/storage.h"
48
#include "storage/storage_simple.h"
49
50
#include "vsha256.h"
51
52
#include "storage/storage_persistent.h"
53
54
#ifdef HAVE_SYS_PERSONALITY_H
55
#include <sys/personality.h>
56
#endif
57
58
#ifndef MAP_NOCORE
59
#define MAP_NOCORE 0 /* XXX Linux */
60
#endif
61
62
#ifndef MAP_NOSYNC
63
#define MAP_NOSYNC 0 /* XXX Linux */
64
#endif
65
66
/*--------------------------------------------------------------------
67
 * Calculate cleaner metrics from silo dimensions
68
 */
69
70
static void
71 23
smp_metrics(struct smp_sc *sc)
72
{
73
74
        /*
75
         * We do not want to loose too big chunks of the silos
76
         * content when we are forced to clean a segment.
77
         *
78
         * For now insist that a segment covers no more than 1% of the silo.
79
         *
80
         * XXX: This should possibly depend on the size of the silo so
81
         * XXX: trivially small silos do not run into trouble along
82
         * XXX: the lines of "one object per segment".
83
         */
84
85 23
        sc->min_nseg = 10;
86 23
        sc->max_segl = smp_stuff_len(sc, SMP_SPC_STUFF) / sc->min_nseg;
87
88 23
        fprintf(stderr, "min_nseg = %u, max_segl = %ju\n",
89
            sc->min_nseg, (uintmax_t)sc->max_segl);
90
91
        /*
92
         * The number of segments are limited by the size of the segment
93
         * table(s) and from that follows the minimum size of a segmement.
94
         */
95
96 23
        sc->max_nseg = smp_stuff_len(sc, SMP_SEG1_STUFF) / sc->min_nseg;
97 23
        sc->min_segl = smp_stuff_len(sc, SMP_SPC_STUFF) / sc->max_nseg;
98
99 138
        while (sc->min_segl < sizeof(struct object)) {
100 92
                sc->max_nseg /= 2;
101 92
                sc->min_segl = smp_stuff_len(sc, SMP_SPC_STUFF) / sc->max_nseg;
102
        }
103
104 23
        fprintf(stderr, "max_nseg = %u, min_segl = %ju\n",
105
            sc->max_nseg, (uintmax_t)sc->min_segl);
106
107
        /*
108
         * Set our initial aim point at the exponential average of the
109
         * two extremes.
110
         *
111
         * XXX: This is a pretty arbitrary choice, but having no idea
112
         * XXX: object count, size distribution or ttl pattern at this
113
         * XXX: point, we have to do something.
114
         */
115
116 23
        sc->aim_nseg =
117 23
           (unsigned) exp((log(sc->min_nseg) + log(sc->max_nseg))*.5);
118 23
        sc->aim_segl = smp_stuff_len(sc, SMP_SPC_STUFF) / sc->aim_nseg;
119
120 23
        fprintf(stderr, "aim_nseg = %u, aim_segl = %ju\n",
121
            sc->aim_nseg, (uintmax_t)sc->aim_segl);
122
123
        /*
124
         * How much space in the free reserve pool ?
125
         */
126 23
        sc->free_reserve = sc->aim_segl * 10;
127
128 23
        fprintf(stderr, "free_reserve = %ju\n", (uintmax_t)sc->free_reserve);
129 23
}
130
131
/*--------------------------------------------------------------------
132
 * Set up persistent storage silo in the master process.
133
 */
134
135
void
136 23
smp_mgt_init(struct stevedore *parent, int ac, char * const *av)
137
{
138
        struct smp_sc           *sc;
139
        struct smp_sign         sgn;
140
        void *target;
141
        int i;
142
143 23
        ASSERT_MGT();
144
145 23
        AZ(av[ac]);
146
147
148
#ifdef HAVE_SYS_PERSONALITY_H
149
        i = personality(0xffffffff); /* Fetch old personality. */
150
        if (!(i & ADDR_NO_RANDOMIZE)) {
151
                i = personality(i | ADDR_NO_RANDOMIZE);
152
                if (i < 0)
153
                        fprintf(stderr, "WARNING: Could not disable ASLR\n");
154
                else
155
                        fprintf(stderr, "NB: Disabled ASLR for Persistent\n");
156
        }
157
#endif
158
159
        /* Necessary alignment. See also smp_object::__filler__ */
160
        assert(sizeof(struct smp_object) % 8 == 0);
161
162
#define SIZOF(foo)       fprintf(stderr, \
163
    "sizeof(%s) = %zu = 0x%zx\n", #foo, sizeof(foo), sizeof(foo));
164 23
        SIZOF(struct smp_ident);
165 23
        SIZOF(struct smp_sign);
166 23
        SIZOF(struct smp_segptr);
167 23
        SIZOF(struct smp_object);
168
#undef SIZOF
169
170
        /* See comments in storage_persistent.h */
171
        assert(sizeof(struct smp_ident) == SMP_IDENT_SIZE);
172
173
        /* Allocate softc */
174 23
        ALLOC_OBJ(sc, SMP_SC_MAGIC);
175 23
        XXXAN(sc);
176 23
        sc->parent = parent;
177 23
        sc->fd = -1;
178 23
        VTAILQ_INIT(&sc->segments);
179
180
        /* Argument processing */
181 23
        if (ac != 2)
182 0
                ARGV_ERR("(-spersistent) wrong number of arguments\n");
183
184 23
        i = STV_GetFile(av[0], &sc->fd, &sc->filename, "-spersistent");
185 23
        if (i == 2)
186 0
                ARGV_ERR("(-spersistent) need filename (not directory)\n");
187
188 23
        sc->align = sizeof(void*) * 2;
189 23
        sc->granularity = getpagesize();
190 23
        sc->mediasize = STV_FileSize(sc->fd, av[1], &sc->granularity,
191
            "-spersistent");
192
193 23
        AZ(ftruncate(sc->fd, sc->mediasize));
194
195
        /* Try to determine correct mmap address */
196 23
        i = read(sc->fd, &sgn, sizeof sgn);
197 23
        assert(i == sizeof sgn);
198 23
        if (!strcmp(sgn.ident, "SILO"))
199 6
                target = (void*)(uintptr_t)sgn.mapped;
200
        else
201 17
                target = NULL;
202
203 23
        sc->base = (void*)mmap(target, sc->mediasize, PROT_READ|PROT_WRITE,
204
            MAP_NOCORE | MAP_NOSYNC | MAP_SHARED, sc->fd, 0);
205
206 23
        if (sc->base == MAP_FAILED)
207 0
                ARGV_ERR("(-spersistent) failed to mmap (%s)\n",
208
                    strerror(errno));
209 23
        if (target != NULL && sc->base != target)
210 0
                fprintf(stderr, "WARNING: Persistent silo lost to ASLR %s\n",
211
                    sc->filename);
212
213 23
        smp_def_sign(sc, &sc->idn, 0, "SILO");
214 23
        sc->ident = SIGN_DATA(&sc->idn);
215
216 23
        i = smp_valid_silo(sc);
217 23
        if (i) {
218 17
                printf("Warning SILO (%s) not reloaded (reason=%d)\n",
219
                    sc->filename, i);
220 17
                smp_newsilo(sc);
221
        }
222 23
        AZ(smp_valid_silo(sc));
223
224 23
        smp_metrics(sc);
225
226 23
        parent->priv = sc;
227
228
        /* XXX: only for sendfile I guess... */
229 23
        MCH_Fd_Inherit(sc->fd, "storage_persistent");
230 23
}