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 36375
STV_next(void)
56
{
57
        static struct stevedore *stv;
58
        struct stevedore *r;
59
60 36375
        PTOK(pthread_mutex_lock(&stv_mtx));
61 36375
        if (!STV__iter(&stv))
62 125
                AN(STV__iter(&stv));
63 36375
        if (stv == stv_transient) {
64 20625
                stv = NULL;
65 20625
                AN(STV__iter(&stv));
66 20625
        }
67 36375
        r = stv;
68 36375
        PTOK(pthread_mutex_unlock(&stv_mtx));
69 36375
        AN(r);
70 36375
        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 66273
STV_NewObject(struct worker *wrk, struct objcore *oc,
81
    const struct stevedore *stv, unsigned wsl)
82
{
83 66273
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
84 66273
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
85 66273
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
86
87 66273
        wrk->strangelove = cache_param->nuke_limit;
88 66273
        AN(stv->allocobj);
89 66273
        if (stv->allocobj(wrk, stv, oc, wsl) == 0) {
90 550
                VSLb(wrk->vsl, SLT_Error,
91
                    "Failed to create object object from %s %s",
92 275
                    stv->name, stv->ident);
93 275
                return (0);
94
        }
95 65998
        oc->oa_present = 0;
96 65998
        wrk->stats->n_object++;
97 131996
        VSLb(wrk->vsl, SLT_Storage, "%s %s",
98 65998
            oc->stobj->stevedore->name, oc->stobj->stevedore->ident);
99 65998
        return (1);
100 66273
}
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 550
STV_AllocBuf(struct worker *wrk, const struct stevedore *stv, size_t size)
114
{
115
        struct stv_buffer *stvbuf;
116
        uint8_t *buf;
117 550
        uintptr_t priv = 0;
118
119 550
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
120 550
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
121
122 550
        if (size == 0)
123 0
                return (NULL);
124 550
        if (stv->allocbuf == NULL)
125 0
                return (NULL);
126
127 550
        wrk->strangelove = cache_param->nuke_limit;
128 550
        buf = stv->allocbuf(wrk, stv, size + PRNDUP(sizeof *stvbuf), &priv);
129 550
        if (buf == NULL)
130 0
                return (NULL);
131
132 550
        assert(PAOK(buf));
133 550
        stvbuf = (void *)buf;
134 550
        INIT_OBJ(stvbuf, STV_BUFFER_MAGIC);
135 550
        stvbuf->stv = stv;
136 550
        stvbuf->priv = priv;
137 550
        stvbuf->size = size;
138
139 550
        return (stvbuf);
140 550
}
141
142
void
143 550
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 550
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
150 550
        TAKE_OBJ_NOTNULL(stvbuf, pstvbuf, STV_BUFFER_MAGIC);
151 550
        CHECK_OBJ_NOTNULL(stvbuf->stv, STEVEDORE_MAGIC);
152
153 550
        stv = stvbuf->stv;
154 550
        priv = stvbuf->priv;
155 550
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
156 550
        ZERO_OBJ(stvbuf, sizeof *stvbuf);
157
158 550
        AN(stv->freebuf);
159 550
        stv->freebuf(wrk, stv, priv);
160 550
}
161
162
void *
163 550
STV_GetBufPtr(struct stv_buffer *stvbuf, size_t *psize)
164
{
165 550
        CHECK_OBJ_NOTNULL(stvbuf, STV_BUFFER_MAGIC);
166 550
        if (psize)
167 550
                *psize = stvbuf->size;
168 550
        return (&stvbuf[1]);
169
}
170
171
/*-------------------------------------------------------------------*/
172
173
void
174 22244
STV_open(void)
175
{
176
        struct stevedore *stv;
177
        char buf[1024];
178
179 22244
        ASSERT_CLI();
180 22244
        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 22244
        AN(mgt_stv_h2_rxbuf);
185
186 22244
        stv_h2_rxbuf = NULL;
187 66782
        STV_Foreach(stv) {
188 44638
                CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
189 44638
                bprintf(buf, "storage.%s", stv->ident);
190 44638
                stv->vclname = strdup(buf);
191 44638
                AN(stv->vclname);
192 44638
                if (stv->open != NULL)
193 44588
                        stv->open(stv);
194 44638
                if (!strcmp(stv->ident, mgt_stv_h2_rxbuf))
195 22144
                        stv_h2_rxbuf = stv;
196
        }
197 22144
        AN(stv_h2_rxbuf);
198 22144
}
199
200
void
201 21900
STV_close(void)
202
{
203
        struct stevedore *stv;
204
        int i;
205
206 21900
        ASSERT_CLI();
207 65700
        for (i = 1; i >= 0; i--) {
208
                /* First send close warning */
209 131900
                STV_Foreach(stv)
210 88100
                        if (stv->close != NULL)
211 1850
                                stv->close(stv, i);
212 43800
        }
213 21900
}
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 1750
STV_BanInfoDrop(const uint8_t *ban, unsigned len)
223
{
224
        struct stevedore *stv;
225 1750
        int r = 0;
226
227 5375
        STV_Foreach(stv)
228 3625
                if (stv->baninfo != NULL)
229 525
                        r |= stv->baninfo(stv, BI_DROP, ban, len);
230
231 1750
        return (r);
232
}
233
234
int
235 24519
STV_BanInfoNew(const uint8_t *ban, unsigned len)
236
{
237
        struct stevedore *stv;
238 24519
        int r = 0;
239
240 73882
        STV_Foreach(stv)
241 49363
                if (stv->baninfo != NULL)
242 1200
                        r |= stv->baninfo(stv, BI_NEW, ban, len);
243
244 24519
        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 44044
STV_BanExport(const uint8_t *bans, unsigned len)
255
{
256
        struct stevedore *stv;
257
258 132632
        STV_Foreach(stv)
259 88588
                if (stv->banexport != NULL)
260 1875
                        stv->banexport(stv, bans, len);
261 44044
}
262
263
/*--------------------------------------------------------------------
264
 * VRT functions for stevedores
265
 */
266
267
static const struct stevedore *
268 1075
stv_find(const char *nm)
269
{
270
        struct stevedore *stv;
271
272 1425
        STV_Foreach(stv)
273 1425
                if (!strcmp(stv->ident, nm))
274 1075
                        return (stv);
275 0
        return (NULL);
276 1075
}
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 425
VRT_STEVEDORE_string(VCL_STEVEDORE s)
289
{
290 425
        if (s == NULL)
291 25
                return (NULL);
292 400
        CHECK_OBJ_NOTNULL(s, STEVEDORE_MAGIC);
293 400
        return (s->vclname);
294 425
}
295
296
VCL_STEVEDORE
297 1075
VRT_stevedore(const char *nm)
298
{
299 1075
        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"