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 3068
STV_next(void)
56
{
57
        static struct stevedore *stv;
58
        struct stevedore *r;
59
60 3068
        PTOK(pthread_mutex_lock(&stv_mtx));
61 3068
        if (!STV__iter(&stv))
62 10
                AN(STV__iter(&stv));
63 3068
        if (stv == stv_transient) {
64 1748
                stv = NULL;
65 1748
                AN(STV__iter(&stv));
66 1748
        }
67 3068
        r = stv;
68 3068
        PTOK(pthread_mutex_unlock(&stv_mtx));
69 3068
        AN(r);
70 3068
        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 5768
STV_NewObject(struct worker *wrk, struct objcore *oc,
81
    const struct stevedore *stv, unsigned wsl)
82
{
83 5768
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
84 5768
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
85 5768
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
86
87 5768
        wrk->strangelove = cache_param->nuke_limit;
88 5768
        AN(stv->allocobj);
89 5768
        if (stv->allocobj(wrk, stv, oc, wsl) == 0) {
90 44
                VSLb(wrk->vsl, SLT_Error,
91
                    "Failed to create object from %s %s",
92 22
                    stv->name, stv->ident);
93 22
                return (0);
94
        }
95 5746
        oc->oa_present = 0;
96 5746
        wrk->stats->n_object++;
97 11492
        VSLb(wrk->vsl, SLT_Storage, "%s %s",
98 5746
            oc->stobj->stevedore->name, oc->stobj->stevedore->ident);
99 5746
        return (1);
100 5768
}
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 588
STV_AllocBuf(struct worker *wrk, const struct stevedore *stv, size_t size)
114
{
115
        struct stv_buffer *stvbuf;
116
        uint8_t *buf;
117 588
        uintptr_t priv = 0;
118
119 588
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
120 588
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
121
122 588
        if (size == 0)
123 0
                return (NULL);
124 588
        if (stv->allocbuf == NULL)
125 0
                return (NULL);
126
127 588
        wrk->strangelove = cache_param->nuke_limit;
128 588
        buf = stv->allocbuf(wrk, stv, size + PRNDUP(sizeof *stvbuf), &priv);
129 588
        if (buf == NULL)
130 0
                return (NULL);
131
132 588
        assert(PAOK(buf));
133 588
        stvbuf = (void *)buf;
134 588
        INIT_OBJ(stvbuf, STV_BUFFER_MAGIC);
135 588
        stvbuf->stv = stv;
136 588
        stvbuf->priv = priv;
137 588
        stvbuf->size = size;
138
139 588
        return (stvbuf);
140 588
}
141
142
void
143 588
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 588
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
150 588
        TAKE_OBJ_NOTNULL(stvbuf, pstvbuf, STV_BUFFER_MAGIC);
151 588
        CHECK_OBJ_NOTNULL(stvbuf->stv, STEVEDORE_MAGIC);
152
153 588
        stv = stvbuf->stv;
154 588
        priv = stvbuf->priv;
155 588
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
156 588
        ZERO_OBJ(stvbuf, sizeof *stvbuf);
157
158 588
        AN(stv->freebuf);
159 588
        stv->freebuf(wrk, stv, priv);
160 588
}
161
162
void *
163 588
STV_GetBufPtr(struct stv_buffer *stvbuf, size_t *psize)
164
{
165 588
        CHECK_OBJ_NOTNULL(stvbuf, STV_BUFFER_MAGIC);
166 588
        if (psize)
167 588
                *psize = stvbuf->size;
168 588
        return (&stvbuf[1]);
169
}
170
171
/*-------------------------------------------------------------------*/
172
173
void
174 1894
STV_open(void)
175
{
176
        struct stevedore *stv;
177
        char buf[1024];
178
179 1894
        ASSERT_CLI();
180 1894
        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 1894
        AN(mgt_stv_h2_rxbuf);
185
186 1894
        stv_h2_rxbuf = NULL;
187 5704
        STV_Foreach(stv) {
188 3810
                CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
189 3810
                bprintf(buf, "storage.%s", stv->ident);
190 3810
                stv->vclname = strdup(buf);
191 3810
                AN(stv->vclname);
192 3810
                if (stv->open != NULL)
193 3810
                        stv->open(stv);
194 3810
                if (!strcmp(stv->ident, mgt_stv_h2_rxbuf))
195 1894
                        stv_h2_rxbuf = stv;
196
        }
197 1894
        AN(stv_h2_rxbuf);
198 1894
}
199
200
void
201 1872
STV_warn(void)
202
{
203
        struct stevedore *stv;
204
205 1872
        ASSERT_CLI();
206 5634
        STV_Foreach(stv)
207 3762
                if (stv->close != NULL)
208 74
                        stv->close(stv, 1);
209 1872
}
210
211
void
212 1872
STV_close(void)
213
{
214
        struct stevedore *stv;
215
216 1872
        ASSERT_CLI();
217 5634
        STV_Foreach(stv)
218 3762
                if (stv->close != NULL)
219 74
                        stv->close(stv, 0);
220 1872
}
221
222
/*-------------------------------------------------------------------
223
 * Notify the stevedores of BAN related events. A non-zero return
224
 * value indicates that the stevedore is unable to persist the
225
 * event.
226
 */
227
228
int
229 144
STV_BanInfoDrop(const uint8_t *ban, unsigned len)
230
{
231
        struct stevedore *stv;
232 144
        int r = 0;
233
234 442
        STV_Foreach(stv)
235 298
                if (stv->baninfo != NULL)
236 42
                        r |= stv->baninfo(stv, BI_DROP, ban, len);
237
238 144
        return (r);
239
}
240
241
int
242 2094
STV_BanInfoNew(const uint8_t *ban, unsigned len)
243
{
244
        struct stevedore *stv;
245 2094
        int r = 0;
246
247 6306
        STV_Foreach(stv)
248 4212
                if (stv->baninfo != NULL)
249 96
                        r |= stv->baninfo(stv, BI_NEW, ban, len);
250
251 2094
        return (r);
252
}
253
254
/*-------------------------------------------------------------------
255
 * Export a complete ban list to the stevedores for persistence.
256
 * The stevedores should clear any previous ban lists and replace
257
 * them with this list.
258
 */
259
260
void
261 3766
STV_BanExport(const uint8_t *bans, unsigned len)
262
{
263
        struct stevedore *stv;
264
265 11334
        STV_Foreach(stv)
266 7568
                if (stv->banexport != NULL)
267 150
                        stv->banexport(stv, bans, len);
268 3766
}
269
270
/*--------------------------------------------------------------------
271
 * VRT functions for stevedores
272
 */
273
274
static const struct stevedore *
275 88
stv_find(const char *nm)
276
{
277
        struct stevedore *stv;
278
279 118
        STV_Foreach(stv)
280 118
                if (!strcmp(stv->ident, nm))
281 88
                        return (stv);
282 0
        return (NULL);
283 88
}
284
285
int
286 0
VRT_Stv(const char *nm)
287
{
288
289 0
        if (stv_find(nm) != NULL)
290 0
                return (1);
291 0
        return (0);
292 0
}
293
294
const char * v_matchproto_()
295 36
VRT_STEVEDORE_string(VCL_STEVEDORE s)
296
{
297 36
        if (s == NULL)
298 2
                return (NULL);
299 34
        CHECK_OBJ_NOTNULL(s, STEVEDORE_MAGIC);
300 34
        return (s->vclname);
301 36
}
302
303
VCL_STEVEDORE
304 88
VRT_stevedore(const char *nm)
305
{
306 88
        return (stv_find(nm));
307
}
308
309
#define VRTSTVVAR(nm, vtype, ctype, dval)               \
310
ctype                                                   \
311
VRT_stevedore_##nm(VCL_STEVEDORE stv)                   \
312
{                                                       \
313
        if (stv == NULL)                                \
314
                return (0);                             \
315
        if (stv->var_##nm == NULL)                      \
316
                return (dval);                          \
317
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);        \
318
        return (stv->var_##nm(stv));                    \
319
}
320
#include "tbl/vrt_stv_var.h"