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 1534
STV_next(void)
56
{
57
        static struct stevedore *stv;
58
        struct stevedore *r;
59
60 1534
        PTOK(pthread_mutex_lock(&stv_mtx));
61 1534
        if (!STV__iter(&stv))
62 5
                AN(STV__iter(&stv));
63 1534
        if (stv == stv_transient) {
64 874
                stv = NULL;
65 874
                AN(STV__iter(&stv));
66 874
        }
67 1534
        r = stv;
68 1534
        PTOK(pthread_mutex_unlock(&stv_mtx));
69 1534
        AN(r);
70 1534
        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 2884
STV_NewObject(struct worker *wrk, struct objcore *oc,
81
    const struct stevedore *stv, unsigned wsl)
82
{
83 2884
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
84 2884
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
85 2884
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
86
87 2884
        wrk->strangelove = cache_param->nuke_limit;
88 2884
        AN(stv->allocobj);
89 2884
        if (stv->allocobj(wrk, stv, oc, wsl) == 0) {
90 22
                VSLb(wrk->vsl, SLT_Error,
91
                    "Failed to create object from %s %s",
92 11
                    stv->name, stv->ident);
93 11
                return (0);
94
        }
95 2873
        oc->oa_present = 0;
96 2873
        wrk->stats->n_object++;
97 5746
        VSLb(wrk->vsl, SLT_Storage, "%s %s",
98 2873
            oc->stobj->stevedore->name, oc->stobj->stevedore->ident);
99 2873
        return (1);
100 2884
}
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 294
STV_AllocBuf(struct worker *wrk, const struct stevedore *stv, size_t size)
114
{
115
        struct stv_buffer *stvbuf;
116
        uint8_t *buf;
117 294
        uintptr_t priv = 0;
118
119 294
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
120 294
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
121
122 294
        if (size == 0)
123 0
                return (NULL);
124 294
        if (stv->allocbuf == NULL)
125 0
                return (NULL);
126
127 294
        wrk->strangelove = cache_param->nuke_limit;
128 294
        buf = stv->allocbuf(wrk, stv, size + PRNDUP(sizeof *stvbuf), &priv);
129 294
        if (buf == NULL)
130 0
                return (NULL);
131
132 294
        assert(PAOK(buf));
133 294
        stvbuf = (void *)buf;
134 294
        INIT_OBJ(stvbuf, STV_BUFFER_MAGIC);
135 294
        stvbuf->stv = stv;
136 294
        stvbuf->priv = priv;
137 294
        stvbuf->size = size;
138
139 294
        return (stvbuf);
140 294
}
141
142
void
143 294
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 294
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
150 294
        TAKE_OBJ_NOTNULL(stvbuf, pstvbuf, STV_BUFFER_MAGIC);
151 294
        CHECK_OBJ_NOTNULL(stvbuf->stv, STEVEDORE_MAGIC);
152
153 294
        stv = stvbuf->stv;
154 294
        priv = stvbuf->priv;
155 294
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
156 294
        ZERO_OBJ(stvbuf, sizeof *stvbuf);
157
158 294
        AN(stv->freebuf);
159 294
        stv->freebuf(wrk, stv, priv);
160 294
}
161
162
void *
163 294
STV_GetBufPtr(struct stv_buffer *stvbuf, size_t *psize)
164
{
165 294
        CHECK_OBJ_NOTNULL(stvbuf, STV_BUFFER_MAGIC);
166 294
        if (psize)
167 294
                *psize = stvbuf->size;
168 294
        return (&stvbuf[1]);
169
}
170
171
/*-------------------------------------------------------------------*/
172
173
void
174 947
STV_open(void)
175
{
176
        struct stevedore *stv;
177
        char buf[1024];
178
179 947
        ASSERT_CLI();
180 947
        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 947
        AN(mgt_stv_h2_rxbuf);
185
186 947
        stv_h2_rxbuf = NULL;
187 2852
        STV_Foreach(stv) {
188 1905
                CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
189 1905
                bprintf(buf, "storage.%s", stv->ident);
190 1905
                stv->vclname = strdup(buf);
191 1905
                AN(stv->vclname);
192 1905
                if (stv->open != NULL)
193 1905
                        stv->open(stv);
194 1905
                if (!strcmp(stv->ident, mgt_stv_h2_rxbuf))
195 947
                        stv_h2_rxbuf = stv;
196
        }
197 947
        AN(stv_h2_rxbuf);
198 947
}
199
200
void
201 936
STV_warn(void)
202
{
203
        struct stevedore *stv;
204
205 936
        ASSERT_CLI();
206 2817
        STV_Foreach(stv)
207 1881
                if (stv->close != NULL)
208 37
                        stv->close(stv, 1);
209 936
}
210
211
void
212 936
STV_close(void)
213
{
214
        struct stevedore *stv;
215
216 936
        ASSERT_CLI();
217 2817
        STV_Foreach(stv)
218 1881
                if (stv->close != NULL)
219 37
                        stv->close(stv, 0);
220 936
}
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 72
STV_BanInfoDrop(const uint8_t *ban, unsigned len)
230
{
231
        struct stevedore *stv;
232 72
        int r = 0;
233
234 221
        STV_Foreach(stv)
235 149
                if (stv->baninfo != NULL)
236 21
                        r |= stv->baninfo(stv, BI_DROP, ban, len);
237
238 72
        return (r);
239
}
240
241
int
242 1047
STV_BanInfoNew(const uint8_t *ban, unsigned len)
243
{
244
        struct stevedore *stv;
245 1047
        int r = 0;
246
247 3153
        STV_Foreach(stv)
248 2106
                if (stv->baninfo != NULL)
249 48
                        r |= stv->baninfo(stv, BI_NEW, ban, len);
250
251 1047
        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 1883
STV_BanExport(const uint8_t *bans, unsigned len)
262
{
263
        struct stevedore *stv;
264
265 5667
        STV_Foreach(stv)
266 3784
                if (stv->banexport != NULL)
267 75
                        stv->banexport(stv, bans, len);
268 1883
}
269
270
/*--------------------------------------------------------------------
271
 * VRT functions for stevedores
272
 */
273
274
static const struct stevedore *
275 44
stv_find(const char *nm)
276
{
277
        struct stevedore *stv;
278
279 59
        STV_Foreach(stv)
280 59
                if (!strcmp(stv->ident, nm))
281 44
                        return (stv);
282 0
        return (NULL);
283 44
}
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 18
VRT_STEVEDORE_string(VCL_STEVEDORE s)
296
{
297 18
        if (s == NULL)
298 1
                return (NULL);
299 17
        CHECK_OBJ_NOTNULL(s, STEVEDORE_MAGIC);
300 17
        return (s->vclname);
301 18
}
302
303
VCL_STEVEDORE
304 44
VRT_stevedore(const char *nm)
305
{
306 44
        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"