|  |  | varnish-cache/bin/varnishd/storage/mgt_stevedore.c | 
|---|
| 0 |  | /*- | 
| 1 |  |  * Copyright (c) 2007-2011 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 <stdio.h> | 
| 38 |  | #include <stdlib.h> | 
| 39 |  | #include <string.h> | 
| 40 |  | #include <unistd.h> | 
| 41 |  |  | 
| 42 |  | #include "mgt/mgt.h" | 
| 43 |  | #include "common/heritage.h" | 
| 44 |  | #include "vcli_serve.h" | 
| 45 |  |  | 
| 46 |  | #include "storage/storage.h" | 
| 47 |  |  | 
| 48 |  | VTAILQ_HEAD(stevedore_head, stevedore); | 
| 49 |  |  | 
| 50 |  | static struct stevedore_head proto_stevedores = | 
| 51 |  |     VTAILQ_HEAD_INITIALIZER(proto_stevedores); | 
| 52 |  |  | 
| 53 |  | static struct stevedore_head pre_stevedores = | 
| 54 |  |     VTAILQ_HEAD_INITIALIZER(pre_stevedores); | 
| 55 |  |  | 
| 56 |  | static struct stevedore_head stevedores = | 
| 57 |  |     VTAILQ_HEAD_INITIALIZER(stevedores); | 
| 58 |  |  | 
| 59 |  | /* Name of transient storage */ | 
| 60 |  | #define TRANSIENT_STORAGE       "Transient" | 
| 61 |  |  | 
| 62 |  | struct stevedore *stv_transient; | 
| 63 |  |  | 
| 64 |  | const char *mgt_stv_h2_rxbuf; | 
| 65 |  |  | 
| 66 |  | /*--------------------------------------------------------------------*/ | 
| 67 |  |  | 
| 68 |  | int | 
| 69 | 293576 | STV__iter(struct stevedore ** const pp) | 
| 70 |  | { | 
| 71 |  |  | 
| 72 | 293576 |         AN(pp); | 
| 73 | 293576 |         CHECK_OBJ_ORNULL(*pp, STEVEDORE_MAGIC); | 
| 74 | 293576 |         if (*pp != NULL) | 
| 75 | 184039 |                 *pp = VTAILQ_NEXT(*pp, list); | 
| 76 | 109537 |         else if (!VTAILQ_EMPTY(&stevedores)) | 
| 77 | 81586 |                 *pp = VTAILQ_FIRST(&stevedores); | 
| 78 |  |         else | 
| 79 | 27951 |                 *pp = VTAILQ_FIRST(&pre_stevedores); | 
| 80 | 293576 |         return (*pp != NULL); | 
| 81 |  | } | 
| 82 |  |  | 
| 83 |  | /*--------------------------------------------------------------------*/ | 
| 84 |  |  | 
| 85 |  | static void v_matchproto_(cli_func_t) | 
| 86 | 44 | stv_cli_list(struct cli *cli, const char * const *av, void *priv) | 
| 87 |  | { | 
| 88 |  |         struct stevedore *stv; | 
| 89 |  |  | 
| 90 | 44 |         ASSERT_MGT(); | 
| 91 | 44 |         (void)av; | 
| 92 | 44 |         (void)priv; | 
| 93 | 44 |         VCLI_Out(cli, "Storage devices:\n"); | 
| 94 | 143 |         STV_Foreach(stv) | 
| 95 | 99 |                 VCLI_Out(cli, "\tstorage.%s = %s\n", stv->ident, stv->name); | 
| 96 | 44 | } | 
| 97 |  |  | 
| 98 |  | static void v_matchproto_(cli_func_t) | 
| 99 | 11 | stv_cli_list_json(struct cli *cli, const char * const *av, void *priv) | 
| 100 |  | { | 
| 101 |  |         struct stevedore *stv; | 
| 102 | 11 |         int n = 0; | 
| 103 |  |  | 
| 104 | 11 |         (void)priv; | 
| 105 | 11 |         ASSERT_MGT(); | 
| 106 | 11 |         VCLI_JSON_begin(cli, 2, av); | 
| 107 | 11 |         VCLI_Out(cli, ",\n"); | 
| 108 | 33 |         STV_Foreach(stv) { | 
| 109 | 22 |                 VCLI_Out(cli, "%s", n ? ",\n" : ""); | 
| 110 | 22 |                 n++; | 
| 111 | 22 |                 VCLI_Out(cli, "{\n"); | 
| 112 | 22 |                 VSB_indent(cli->sb, 2); | 
| 113 | 22 |                 VCLI_Out(cli, "\"name\": "); | 
| 114 | 22 |                 VCLI_JSON_str(cli, stv->ident); | 
| 115 | 22 |                 VCLI_Out(cli, ",\n"); | 
| 116 | 22 |                 VCLI_Out(cli, "\"storage\": "); | 
| 117 | 22 |                 VCLI_JSON_str(cli, stv->name); | 
| 118 | 22 |                 VSB_indent(cli->sb, -2); | 
| 119 | 22 |                 VCLI_Out(cli, "\n}"); | 
| 120 |  |         } | 
| 121 | 11 |         VCLI_JSON_end(cli); | 
| 122 | 11 | } | 
| 123 |  |  | 
| 124 |  | /*--------------------------------------------------------------------*/ | 
| 125 |  |  | 
| 126 |  | static struct cli_proto cli_stv[] = { | 
| 127 |  |         { CLICMD_STORAGE_LIST,          "", stv_cli_list, stv_cli_list_json }, | 
| 128 |  |         { NULL} | 
| 129 |  | }; | 
| 130 |  |  | 
| 131 |  | /*-------------------------------------------------------------------- | 
| 132 |  |  */ | 
| 133 |  |  | 
| 134 |  | #ifdef WITH_PERSISTENT_STORAGE | 
| 135 |  | static void v_noreturn_ v_matchproto_(storage_init_f) | 
| 136 | 11 | smp_fake_init(struct stevedore *parent, int ac, char * const *av) | 
| 137 |  | { | 
| 138 |  |  | 
| 139 | 11 |         (void)parent; | 
| 140 | 11 |         (void)ac; | 
| 141 | 11 |         (void)av; | 
| 142 | 11 |         ARGV_ERR( | 
| 143 |  |             "-spersistent has been deprecated, please see:\n" | 
| 144 |  |             "  https://www.varnish-cache.org/docs/trunk/phk/persistent.html\n" | 
| 145 |  |             "for details.\n" | 
| 146 |  |         ); | 
| 147 | 0 | } | 
| 148 |  |  | 
| 149 |  | static const struct stevedore smp_fake_stevedore = { | 
| 150 |  |         .magic = STEVEDORE_MAGIC, | 
| 151 |  |         .name = "persistent", | 
| 152 |  |         .init = smp_fake_init, | 
| 153 |  | }; | 
| 154 |  | #endif | 
| 155 |  |  | 
| 156 |  | /*-------------------------------------------------------------------- | 
| 157 |  |  * Register a stevedore implementation by name. | 
| 158 |  |  * VEXTs get to do this first, and since the list is searched front to | 
| 159 |  |  * back a VEXT stevedore which inadvisably wants to steal "default" or | 
| 160 |  |  * the name of another stevedore implementation can do so. | 
| 161 |  |  */ | 
| 162 |  |  | 
| 163 |  | void | 
| 164 | 63228 | STV_Register(const struct stevedore *cstv, const char *altname) | 
| 165 |  | { | 
| 166 |  |         struct stevedore *stv; | 
| 167 |  |  | 
| 168 | 63228 |         CHECK_OBJ_NOTNULL(cstv, STEVEDORE_MAGIC); | 
| 169 | 63228 |         ALLOC_OBJ(stv, STEVEDORE_MAGIC); | 
| 170 | 63228 |         AN(stv); | 
| 171 | 63228 |         *stv = *cstv; | 
| 172 | 63228 |         if (altname != NULL) | 
| 173 | 10538 |                 stv->ident = altname; | 
| 174 |  |         else | 
| 175 | 52690 |                 stv->ident = stv->name; | 
| 176 | 63228 |         VTAILQ_INSERT_TAIL(&proto_stevedores, stv, list); | 
| 177 | 63228 | } | 
| 178 |  |  | 
| 179 |  | static void | 
| 180 | 10538 | STV_Register_The_Usual_Suspects(void) | 
| 181 |  | { | 
| 182 | 10538 |         STV_Register(&smf_stevedore, NULL); | 
| 183 | 10538 |         STV_Register(&sma_stevedore, NULL); | 
| 184 | 10538 |         STV_Register(&smd_stevedore, NULL); | 
| 185 |  | #ifdef WITH_PERSISTENT_STORAGE | 
| 186 | 10538 |         STV_Register(&smp_stevedore, NULL); | 
| 187 | 10538 |         STV_Register(&smp_fake_stevedore, NULL); | 
| 188 |  | #endif | 
| 189 |  | #if defined(HAVE_UMEM_H) | 
| 190 |  |         STV_Register(&smu_stevedore, NULL); | 
| 191 |  |         STV_Register(&smu_stevedore, "default"); | 
| 192 |  | #else | 
| 193 | 10538 |         STV_Register(&sma_stevedore, "default"); | 
| 194 |  | #endif | 
| 195 | 10538 | } | 
| 196 |  |  | 
| 197 |  | /*-------------------------------------------------------------------- | 
| 198 |  |  * Parse a stevedore argument on the form: | 
| 199 |  |  *     [ name '=' ] strategy [ ',' arg ] * | 
| 200 |  |  */ | 
| 201 |  |  | 
| 202 |  | void | 
| 203 | 21791 | STV_Config(const char *spec) | 
| 204 |  | { | 
| 205 |  |         char **av, buf[8]; | 
| 206 |  |         const char *ident; | 
| 207 |  |         struct stevedore *stv; | 
| 208 |  |         static unsigned seq = 0; | 
| 209 |  |  | 
| 210 | 21791 |         av = MGT_NamedArg(spec, &ident, "-s"); | 
| 211 | 21791 |         AN(av); | 
| 212 |  |  | 
| 213 | 21791 |         if (av[1] == NULL) | 
| 214 | 0 |                 ARGV_ERR("-s argument lacks strategy {malloc, file, ...}\n"); | 
| 215 |  |  | 
| 216 |  |         /* Append strategy to ident string */ | 
| 217 | 21791 |         VSB_printf(vident, ",-s%s", av[1]); | 
| 218 |  |  | 
| 219 | 21791 |         if (ident == NULL) { | 
| 220 | 10593 |                 bprintf(buf, "s%u", seq++); | 
| 221 | 10593 |                 ident = strdup(buf); | 
| 222 | 10593 |         } | 
| 223 |  |  | 
| 224 | 32923 |         VTAILQ_FOREACH(stv, &pre_stevedores, list) | 
| 225 | 11165 |                 if (!strcmp(stv->ident, ident)) | 
| 226 | 33 |                         ARGV_ERR("(-s %s) '%s' is already defined\n", | 
| 227 |  |                             spec, ident); | 
| 228 |  |  | 
| 229 | 21758 |         ALLOC_OBJ(stv, STEVEDORE_MAGIC); | 
| 230 | 21758 |         AN(stv); | 
| 231 | 21758 |         stv->av = av; | 
| 232 | 21758 |         stv->ident = ident; | 
| 233 | 21758 |         stv->name = av[1]; | 
| 234 | 21758 |         VTAILQ_INSERT_TAIL(&pre_stevedores, stv, list); | 
| 235 | 21758 | } | 
| 236 |  |  | 
| 237 |  | /*--------------------------------------------------------------------*/ | 
| 238 |  |  | 
| 239 |  | void | 
| 240 | 10846 | STV_Config_Final(void) | 
| 241 |  | { | 
| 242 |  |         struct stevedore *stv; | 
| 243 | 10846 |         ASSERT_MGT(); | 
| 244 |  |  | 
| 245 | 10846 |         VCLS_AddFunc(mgt_cls, MCF_AUTH, cli_stv); | 
| 246 | 21703 |         STV_Foreach(stv) | 
| 247 | 11099 |                 if (!strcmp(stv->ident, TRANSIENT_STORAGE)) | 
| 248 | 242 |                         return; | 
| 249 | 10604 |         STV_Config(TRANSIENT_STORAGE "=default"); | 
| 250 | 10846 | } | 
| 251 |  |  | 
| 252 |  | /*-------------------------------------------------------------------- | 
| 253 |  |  * Initialize configured stevedores in the worker process | 
| 254 |  |  */ | 
| 255 |  |  | 
| 256 |  | void | 
| 257 | 10615 | STV_Init(void) | 
| 258 |  | { | 
| 259 |  |         char **av; | 
| 260 |  |         const char *ident; | 
| 261 |  |         struct stevedore *stv; | 
| 262 |  |         const struct stevedore *stv2; | 
| 263 |  |         int ac; | 
| 264 |  |  | 
| 265 | 10615 |         STV_Register_The_Usual_Suspects(); | 
| 266 | 31647 |         while (!VTAILQ_EMPTY(&pre_stevedores)) { | 
| 267 | 21186 |                 stv = VTAILQ_FIRST(&pre_stevedores); | 
| 268 | 21186 |                 VTAILQ_REMOVE(&pre_stevedores, stv, list); | 
| 269 | 21186 |                 CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC); | 
| 270 | 21186 |                 AN(stv->av); | 
| 271 | 21186 |                 av = stv->av; | 
| 272 | 21186 |                 AN(stv->ident); | 
| 273 | 21186 |                 ident = stv->ident; | 
| 274 |  |  | 
| 275 | 32428 |                 for (ac = 0; av[ac + 2] != NULL; ac++) | 
| 276 | 11242 |                         continue; | 
| 277 |  |  | 
| 278 | 124740 |                 VTAILQ_FOREACH(stv2, &proto_stevedores, list) | 
| 279 | 124663 |                         if (!strcmp(stv2->ident, av[1])) | 
| 280 | 21109 |                                 break; | 
| 281 | 21186 |                 if (stv2 == NULL) | 
| 282 | 0 |                         ARGV_ERR("Unknown stevedore method \"%s\"\n", av[1]); | 
| 283 |  |  | 
| 284 | 21032 |                 CHECK_OBJ_NOTNULL(stv2, STEVEDORE_MAGIC); | 
| 285 | 21032 |                 *stv = *stv2; | 
| 286 | 21032 |                 AN(stv->name); | 
| 287 |  |  | 
| 288 | 21032 |                 av += 2; | 
| 289 |  |  | 
| 290 | 21032 |                 stv->ident = ident; | 
| 291 | 21032 |                 stv->av = av; | 
| 292 |  |  | 
| 293 | 21032 |                 if (stv->init != NULL) | 
| 294 | 21032 |                         stv->init(stv, ac, av); | 
| 295 | 0 |                 else if (ac != 0) | 
| 296 | 0 |                         ARGV_ERR("(-s %s) too many arguments\n", stv->name); | 
| 297 |  |  | 
| 298 | 21032 |                 AN(stv->allocobj); | 
| 299 | 21032 |                 AN(stv->methods); | 
| 300 |  |  | 
| 301 | 21032 |                 if (!strcmp(stv->ident, TRANSIENT_STORAGE)) { | 
| 302 | 10461 |                         AZ(stv_transient); | 
| 303 | 10461 |                         stv_transient = stv; | 
| 304 | 10461 |                 } else | 
| 305 | 10571 |                         VTAILQ_INSERT_TAIL(&stevedores, stv, list); | 
| 306 |  |                 /* NB: Do not free av, stevedore gets to keep it */ | 
| 307 |  |         } | 
| 308 | 10461 |         AN(stv_transient); | 
| 309 | 10461 |         VTAILQ_INSERT_TAIL(&stevedores, stv_transient, list); | 
| 310 | 10461 | } |