| | 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" |