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