varnish-cache/bin/varnishd/storage/stevedore.c
0
/*-
1
 * Copyright (c) 2007-2015 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Dag-Erling Smørgav <des@des.no>
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
 * STEVEDORE: one who works at or is responsible for loading and
30
 * unloading ships in port.  Example: "on the wharves, stevedores were
31
 * unloading cargo from the far corners of the world." Origin: Spanish
32
 * estibador, from estibar to pack.  First Known Use: 1788
33
 */
34
35
#include "config.h"
36
37
#include "cache/cache_varnishd.h"
38
39
#include <stdio.h>
40
#include <stdlib.h>
41
42
#include "storage/storage.h"
43
#include "vrt_obj.h"
44
45
extern const char *mgt_stv_h2_rxbuf;
46
struct stevedore *stv_h2_rxbuf = NULL;
47
48
static pthread_mutex_t stv_mtx;
49
50
/*--------------------------------------------------------------------
51
 * XXX: trust pointer writes to be atomic
52
 */
53
54
const struct stevedore *
55 59000
STV_next(void)
56
{
57
        static struct stevedore *stv;
58
        struct stevedore *r;
59
60 59000
        PTOK(pthread_mutex_lock(&stv_mtx));
61 59000
        if (!STV__iter(&stv))
62 200
                AN(STV__iter(&stv));
63 59000
        if (stv == stv_transient) {
64 33400
                stv = NULL;
65 33400
                AN(STV__iter(&stv));
66 33400
        }
67 59000
        r = stv;
68 59000
        PTOK(pthread_mutex_unlock(&stv_mtx));
69 59000
        AN(r);
70 59000
        return (r);
71
}
72
73
/*-------------------------------------------------------------------
74
 * Allocate storage for an object, based on the header information.
75
 * XXX: If we know (a hint of) the length, we could allocate space
76
 * XXX: for the body in the same allocation while we are at it.
77
 */
78
79
int
80 111719
STV_NewObject(struct worker *wrk, struct objcore *oc,
81
    const struct stevedore *stv, unsigned wsl)
82
{
83 111719
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
84 111719
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
85 111719
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
86
87 111719
        wrk->strangelove = cache_param->nuke_limit;
88 111719
        AN(stv->allocobj);
89 111719
        if (stv->allocobj(wrk, stv, oc, wsl) == 0) {
90 880
                VSLb(wrk->vsl, SLT_Error,
91
                    "Failed to create object from %s %s",
92 440
                    stv->name, stv->ident);
93 440
                return (0);
94
        }
95 111279
        oc->oa_present = 0;
96 111279
        wrk->stats->n_object++;
97 222558
        VSLb(wrk->vsl, SLT_Storage, "%s %s",
98 111279
            oc->stobj->stevedore->name, oc->stobj->stevedore->ident);
99 111279
        return (1);
100 111719
}
101
102
/*-------------------------------------------------------------------*/
103
104
struct stv_buffer {
105
        unsigned                magic;
106
#define STV_BUFFER_MAGIC        0xf39cb6c2
107
        const struct stevedore  *stv;
108
        size_t                  size;
109
        uintptr_t               priv;
110
};
111
112
struct stv_buffer *
113 880
STV_AllocBuf(struct worker *wrk, const struct stevedore *stv, size_t size)
114
{
115
        struct stv_buffer *stvbuf;
116
        uint8_t *buf;
117 880
        uintptr_t priv = 0;
118
119 880
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
120 880
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
121
122 880
        if (size == 0)
123 0
                return (NULL);
124 880
        if (stv->allocbuf == NULL)
125 0
                return (NULL);
126
127 880
        wrk->strangelove = cache_param->nuke_limit;
128 880
        buf = stv->allocbuf(wrk, stv, size + PRNDUP(sizeof *stvbuf), &priv);
129 880
        if (buf == NULL)
130 0
                return (NULL);
131
132 880
        assert(PAOK(buf));
133 880
        stvbuf = (void *)buf;
134 880
        INIT_OBJ(stvbuf, STV_BUFFER_MAGIC);
135 880
        stvbuf->stv = stv;
136 880
        stvbuf->priv = priv;
137 880
        stvbuf->size = size;
138
139 880
        return (stvbuf);
140 880
}
141
142
void
143 880
STV_FreeBuf(struct worker *wrk, struct stv_buffer **pstvbuf)
144
{
145
        struct stv_buffer *stvbuf;
146
        const struct stevedore *stv;
147
        uintptr_t priv;
148
149 880
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
150 880
        TAKE_OBJ_NOTNULL(stvbuf, pstvbuf, STV_BUFFER_MAGIC);
151 880
        CHECK_OBJ_NOTNULL(stvbuf->stv, STEVEDORE_MAGIC);
152
153 880
        stv = stvbuf->stv;
154 880
        priv = stvbuf->priv;
155 880
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
156 880
        ZERO_OBJ(stvbuf, sizeof *stvbuf);
157
158 880
        AN(stv->freebuf);
159 880
        stv->freebuf(wrk, stv, priv);
160 880
}
161
162
void *
163 880
STV_GetBufPtr(struct stv_buffer *stvbuf, size_t *psize)
164
{
165 880
        CHECK_OBJ_NOTNULL(stvbuf, STV_BUFFER_MAGIC);
166 880
        if (psize)
167 880
                *psize = stvbuf->size;
168 880
        return (&stvbuf[1]);
169
}
170
171
/*-------------------------------------------------------------------*/
172
173
void
174 36591
STV_open(void)
175
{
176
        struct stevedore *stv;
177
        char buf[1024];
178
179 36591
        ASSERT_CLI();
180 36591
        PTOK(pthread_mutex_init(&stv_mtx, &mtxattr_errorcheck));
181
182
        /* This string was prepared for us before the fork, and should
183
         * point to a configured stevedore. */
184 36591
        AN(mgt_stv_h2_rxbuf);
185
186 36591
        stv_h2_rxbuf = NULL;
187 110253
        STV_Foreach(stv) {
188 73662
                CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
189 73662
                bprintf(buf, "storage.%s", stv->ident);
190 73662
                stv->vclname = strdup(buf);
191 73662
                AN(stv->vclname);
192 73662
                if (stv->open != NULL)
193 73662
                        stv->open(stv);
194 73662
                if (!strcmp(stv->ident, mgt_stv_h2_rxbuf))
195 36591
                        stv_h2_rxbuf = stv;
196
        }
197 36591
        AN(stv_h2_rxbuf);
198 36591
}
199
200
void
201 36160
STV_close(void)
202
{
203
        struct stevedore *stv;
204
        int i;
205
206 36160
        ASSERT_CLI();
207 108480
        for (i = 1; i >= 0; i--) {
208
                /* First send close warning */
209 217760
                STV_Foreach(stv)
210 145440
                        if (stv->close != NULL)
211 2960
                                stv->close(stv, i);
212 72320
        }
213 36160
}
214
215
/*-------------------------------------------------------------------
216
 * Notify the stevedores of BAN related events. A non-zero return
217
 * value indicates that the stevedore is unable to persist the
218
 * event.
219
 */
220
221
int
222 2804
STV_BanInfoDrop(const uint8_t *ban, unsigned len)
223
{
224
        struct stevedore *stv;
225 2804
        int r = 0;
226
227 8612
        STV_Foreach(stv)
228 5808
                if (stv->baninfo != NULL)
229 840
                        r |= stv->baninfo(stv, BI_DROP, ban, len);
230
231 2804
        return (r);
232
}
233
234
int
235 40391
STV_BanInfoNew(const uint8_t *ban, unsigned len)
236
{
237
        struct stevedore *stv;
238 40391
        int r = 0;
239
240 121693
        STV_Foreach(stv)
241 81302
                if (stv->baninfo != NULL)
242 1920
                        r |= stv->baninfo(stv, BI_NEW, ban, len);
243
244 40391
        return (r);
245
}
246
247
/*-------------------------------------------------------------------
248
 * Export a complete ban list to the stevedores for persistence.
249
 * The stevedores should clear any previous ban lists and replace
250
 * them with this list.
251
 */
252
253
void
254 72751
STV_BanExport(const uint8_t *bans, unsigned len)
255
{
256
        struct stevedore *stv;
257
258 219053
        STV_Foreach(stv)
259 146302
                if (stv->banexport != NULL)
260 3000
                        stv->banexport(stv, bans, len);
261 72751
}
262
263
/*--------------------------------------------------------------------
264
 * VRT functions for stevedores
265
 */
266
267
static const struct stevedore *
268 1720
stv_find(const char *nm)
269
{
270
        struct stevedore *stv;
271
272 2280
        STV_Foreach(stv)
273 2280
                if (!strcmp(stv->ident, nm))
274 1720
                        return (stv);
275 0
        return (NULL);
276 1720
}
277
278
int
279 0
VRT_Stv(const char *nm)
280
{
281
282 0
        if (stv_find(nm) != NULL)
283 0
                return (1);
284 0
        return (0);
285 0
}
286
287
const char * v_matchproto_()
288 680
VRT_STEVEDORE_string(VCL_STEVEDORE s)
289
{
290 680
        if (s == NULL)
291 40
                return (NULL);
292 640
        CHECK_OBJ_NOTNULL(s, STEVEDORE_MAGIC);
293 640
        return (s->vclname);
294 680
}
295
296
VCL_STEVEDORE
297 1720
VRT_stevedore(const char *nm)
298
{
299 1720
        return (stv_find(nm));
300
}
301
302
#define VRTSTVVAR(nm, vtype, ctype, dval)               \
303
ctype                                                   \
304
VRT_stevedore_##nm(VCL_STEVEDORE stv)                   \
305
{                                                       \
306
        if (stv == NULL)                                \
307
                return (0);                             \
308
        if (stv->var_##nm == NULL)                      \
309
                return (dval);                          \
310
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);        \
311
        return (stv->var_##nm(stv));                    \
312
}
313
#include "tbl/vrt_stv_var.h"