varnish-cache/lib/libvarnishapi/vsm.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
#include "config.h"
33
34
#include <sys/mman.h>
35
#include <sys/stat.h>
36
37
#include <fcntl.h>
38
#include <float.h>
39
#include <math.h>
40
#include <stdarg.h>
41
#include <stdint.h>
42
#include <stdio.h>
43
#include <stdlib.h>
44
#include <string.h>
45
#include <unistd.h>
46
47
#include "vdef.h"
48
#include "vas.h"
49
#include "miniobj.h"
50
51
#include "vav.h"
52
#include "vin.h"
53
#include "vlu.h"
54
#include "vsb.h"
55
#include "vsm_priv.h"
56
#include "vqueue.h"
57
#include "vtim.h"
58
59
#include "vapi/vsig.h"
60
#include "vapi/vsm.h"
61
62
#ifndef MAP_HASSEMAPHORE
63
#  define MAP_HASSEMAPHORE 0 /* XXX Linux */
64
#endif
65
66
#ifndef MAP_NOSYNC
67
#  define MAP_NOSYNC 0 /* XXX Linux */
68
#endif
69
70
const struct vsm_valid VSM_invalid[1] = {{"invalid"}};
71
const struct vsm_valid VSM_valid[1] = {{"valid"}};
72
73
static vlu_f vsm_vlu_func;
74
75
#define VSM_PRIV_SHIFT                                                  \
76
        (sizeof (uint64_t) * 4)
77
#define VSM_PRIV_MASK                                                   \
78
        ((1ULL << VSM_PRIV_SHIFT) - 1)
79
#define VSM_PRIV_LOW(u)                                                 \
80
        ((uint64_t)(u) & VSM_PRIV_MASK)
81
#define VSM_PRIV_HIGH(u)                                                \
82
        (((uint64_t)(u) >> VSM_PRIV_SHIFT) & VSM_PRIV_MASK)
83
#define VSM_PRIV_MERGE(low, high)                                       \
84
        (VSM_PRIV_LOW(low) | (VSM_PRIV_LOW(high) << VSM_PRIV_SHIFT))
85
86
/*--------------------------------------------------------------------*/
87
88
struct vsm_set;
89
90
struct vsm_seg {
91
        unsigned                magic;
92
#define VSM_SEG_MAGIC           0xeb6c6dfd
93
        unsigned                flags;
94
#define VSM_FLAG_MARKSCAN       (1U<<1)
95
#define VSM_FLAG_STALE          (1U<<2)
96
#define VSM_FLAG_CLUSTER        (1U<<3)
97
        VTAILQ_ENTRY(vsm_seg)   list;
98
        VTAILQ_ENTRY(vsm_seg)   clist;
99
        struct vsm_set          *set;
100
        struct vsm_seg          *cluster;
101
        char                    **av;
102
        int                     refs;
103
        void                    *s;
104
        size_t                  sz;
105
        void                    *b;
106
        void                    *e;
107
        uint64_t                serial;
108
};
109
110
struct vsm_set {
111
        unsigned                magic;
112
#define VSM_SET_MAGIC           0xdee401b8
113
        const char              *dname;
114
        struct vsm              *vsm;
115
        VTAILQ_HEAD(,vsm_seg)   segs;
116
        VTAILQ_HEAD(,vsm_seg)   stale;
117
        VTAILQ_HEAD(,vsm_seg)   clusters;
118
119
        int                     dfd;
120
        struct stat             dst;
121
122
        int                     fd;
123
        struct stat             fst;
124
125
        uintmax_t               id1, id2;
126
127
        // _.index reading state
128
        struct vlu              *vlu;
129
        unsigned                retval;
130
        struct vsm_seg          *vg;
131
132
        unsigned                flag_running;
133
        unsigned                flag_changed;
134
        unsigned                flag_restarted;
135
136
        int                     couldkill;
137
};
138
139
struct vsm {
140
        unsigned                magic;
141
#define VSM_MAGIC               0x6e3bd69b
142
143
        struct vsb              *diag;
144
        uint64_t                serial;
145
146
        int                     wdfd;
147
        struct stat             wdst;
148
        char                    *wdname;
149
150
        struct vsm_set          *mgt;
151
        struct vsm_set          *child;
152
153
        int                     attached;
154
        double                  patience;
155
};
156
157
/*--------------------------------------------------------------------*/
158
159
static int
160 780
vsm_diag(struct vsm *vd, const char *fmt, ...)
161
{
162
        va_list ap;
163
164 780
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
165 780
        AN(fmt);
166
167 780
        if (vd->diag == NULL)
168 779
                vd->diag = VSB_new_auto();
169 780
        AN(vd->diag);
170 780
        VSB_clear(vd->diag);
171 780
        va_start(ap, fmt);
172 780
        VSB_vprintf(vd->diag, fmt, ap);
173 780
        va_end(ap);
174 780
        AZ(VSB_finish(vd->diag));
175 780
        return (-1);
176
}
177
178
/*--------------------------------------------------------------------*/
179
180
static int
181 109326
vsm_mapseg(struct vsm *vd, struct vsm_seg *vg)
182
{
183
        size_t of, off, sz, ps, len;
184
        struct vsb *vsb;
185
        void *s;
186
        int fd;
187
188 109326
        CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
189
190 109326
        if (vg->s != NULL)
191 1717
                return (0);
192
193 107609
        ps = getpagesize();
194
195 107609
        of = strtoul(vg->av[2], NULL, 10);
196 107609
        off = RDN2(of, ps);
197
198 107609
        if (vg->flags & VSM_FLAG_CLUSTER)
199 738
                assert(of == 0);
200 107609
        assert(vg->cluster == NULL);
201
202 107609
        sz = strtoul(vg->av[3], NULL, 10);
203 107609
        assert(sz > 0);
204 107609
        assert(of >= off);
205 107609
        len = RUP2((of - off) + sz, ps);
206
207 107609
        vsb = VSB_new_auto();
208 107609
        AN(vsb);
209 107609
        VSB_printf(vsb, "%s/%s/%s", vd->wdname, vg->set->dname, vg->av[1]);
210 107609
        AZ(VSB_finish(vsb));
211
212 107609
        fd = open(VSB_data(vsb), O_RDONLY);     // XXX: openat
213 107609
        if (fd < 0) {
214 12
                VSB_destroy(&vsb);
215 12
                return (vsm_diag(vd, "Could not open segment"));
216
        }
217
218 215194
        s = (void*)mmap(NULL, len,
219
            PROT_READ,
220
            MAP_HASSEMAPHORE | MAP_NOSYNC | MAP_SHARED,
221 107597
            fd, (off_t)off);
222
223 107597
        VSB_destroy(&vsb);
224
225 107597
        closefd(&fd);
226 107597
        if (s == MAP_FAILED)
227 0
                return (vsm_diag(vd, "Could not mmap segment"));
228
229 107597
        vg->s = s;
230 107597
        vg->b = (char*)(vg->s) + of - off;
231 107597
        vg->e = (char *)vg->b + sz;
232 107597
        vg->sz = len;
233
234 107597
        return (0);
235 109326
}
236
237
static void
238 96173
vsm_unmapseg(struct vsm_seg *vg)
239
{
240
241 96173
        CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
242
243 96173
        AN(vg->b);
244 96173
        AN(vg->e);
245 96173
        AZ(munmap(vg->s, vg->sz));
246 96173
        vg->s = vg->b = vg->e = NULL;
247 96173
        vg->sz = 0;
248 96173
}
249
250
/*--------------------------------------------------------------------*/
251
252
static void
253 1322622
vsm_delseg(struct vsm_seg *vg, int refsok)
254
{
255
256 1322622
        CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
257
258 1322622
        if (vg->set->vg == vg) {
259 82367
                AZ(vg->flags & VSM_FLAG_STALE);
260 82367
                vg->set->vg = VTAILQ_NEXT(vg, list);
261 82367
        }
262
263 1322622
        if (refsok && vg->refs) {
264 2291
                AZ(vg->flags & VSM_FLAG_STALE);
265 2291
                vg->flags |= VSM_FLAG_STALE;
266 2291
                VTAILQ_REMOVE(&vg->set->segs, vg, list);
267 2291
                VTAILQ_INSERT_TAIL(&vg->set->stale, vg, list);
268 2291
                return;
269
        }
270
271 1320331
        if (vg->s != NULL)
272 0
                vsm_unmapseg(vg);
273
274 1320331
        if (vg->flags & VSM_FLAG_CLUSTER) {
275 32521
                vg->flags &= ~VSM_FLAG_CLUSTER;
276 32521
                VTAILQ_REMOVE(&vg->set->clusters, vg, clist);
277 32521
        }
278
279 1320331
        if (vg->flags & VSM_FLAG_STALE)
280 2291
                VTAILQ_REMOVE(&vg->set->stale, vg, list);
281
        else
282 1318040
                VTAILQ_REMOVE(&vg->set->segs, vg, list);
283 1320331
        VAV_Free(vg->av);
284 1320331
        FREE_OBJ(vg);
285 1322622
}
286
287
/*--------------------------------------------------------------------*/
288
289
static struct vsm_set *
290 76534
vsm_newset(const char *dirname)
291
{
292
        struct vsm_set *vs;
293
294 76534
        ALLOC_OBJ(vs, VSM_SET_MAGIC);
295 76534
        AN(vs);
296 76534
        VTAILQ_INIT(&vs->segs);
297 76534
        VTAILQ_INIT(&vs->stale);
298 76534
        VTAILQ_INIT(&vs->clusters);
299 76534
        vs->dname = dirname;
300 76534
        vs->dfd = vs->fd = -1;
301 76534
        vs->vlu = VLU_New(vsm_vlu_func, vs, 0);
302 76534
        AN(vs->vlu);
303 76534
        if (getenv("VSM_NOPID") != NULL)
304 0
                vs->couldkill = -1;
305 76534
        return (vs);
306
}
307
308
static void
309 75582
vsm_delset(struct vsm_set **p)
310
{
311
        struct vsm_set *vs;
312
        struct vsm_seg *vg;
313
314 75582
        TAKE_OBJ_NOTNULL(vs, p, VSM_SET_MAGIC);
315
316 75582
        if (vs->fd >= 0)
317 46376
                closefd(&vs->fd);
318 75582
        if (vs->dfd >= 0)
319 62220
                closefd(&vs->dfd);
320 75582
        while ((vg = VTAILQ_FIRST(&vs->stale)) != NULL) {
321 0
                AN(vg->flags & VSM_FLAG_STALE);
322 0
                vsm_delseg(vg, 0);
323
        }
324 1318601
        while ((vg = VTAILQ_FIRST(&vs->segs)) != NULL) {
325 1243019
                AZ(vg->flags & VSM_FLAG_STALE);
326 1243019
                vsm_delseg(vg, 0);
327
        }
328 75582
        assert(VTAILQ_EMPTY(&vs->clusters));
329 75582
        VLU_Destroy(&vs->vlu);
330 75582
        FREE_OBJ(vs);
331 75582
}
332
333
static void
334 167179
vsm_wash_set(const struct vsm_set *vs, int all)
335
{
336
        struct vsm_seg *vg, *vg2;
337
338 1433661
        VTAILQ_FOREACH_SAFE(vg, &vs->segs, list, vg2) {
339 1266482
                if (all || (vg->flags & VSM_FLAG_MARKSCAN) == 0)
340 44113
                        vsm_delseg(vg, 1);
341 1266482
        }
342 167179
}
343
344
/*--------------------------------------------------------------------*/
345
346
struct vsm *
347 38267
VSM_New(void)
348
{
349
        struct vsm *vd;
350
351 38267
        ALLOC_OBJ(vd, VSM_MAGIC);
352 38267
        AN(vd);
353
354 38267
        vd->mgt = vsm_newset(VSM_MGT_DIRNAME);
355 38267
        vd->mgt->flag_running = VSM_MGT_RUNNING;
356 38267
        vd->mgt->flag_changed = VSM_MGT_CHANGED;
357 38267
        vd->mgt->flag_restarted = VSM_MGT_RESTARTED;
358
359 38267
        vd->child = vsm_newset(VSM_CHILD_DIRNAME);
360 38267
        vd->child->flag_running = VSM_WRK_RUNNING;
361 38267
        vd->child->flag_changed = VSM_WRK_CHANGED;
362 38267
        vd->child->flag_restarted = VSM_WRK_RESTARTED;
363
364 38267
        vd->mgt->vsm = vd;
365 38267
        vd->child->vsm = vd;
366 38267
        vd->wdfd = -1;
367 38267
        vd->patience = 5;
368 38267
        return (vd);
369
}
370
371
/*--------------------------------------------------------------------*/
372
373
int
374 39015
VSM_Arg(struct vsm *vd, char flag, const char *arg)
375
{
376 39015
        char *p = NULL;
377
378 39015
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
379
380 39015
        if (arg == NULL)
381 697
                return (1);
382 38318
        switch (flag) {
383
        case 't':
384 221
                if (!strcasecmp(arg, "off")) {
385 0
                        vd->patience = -1;
386 0
                } else {
387 221
                        vd->patience = strtod(arg, &p);
388 357
                        if ((p != NULL && *p != '\0') ||
389 136
                            !isfinite(vd->patience) || vd->patience < 0)
390 238
                                return (vsm_diag(vd,
391 119
                                    "-t: Invalid argument: %s", arg));
392
                }
393 102
                break;
394
        case 'n':
395 38097
                if (vd->wdname != NULL)
396 0
                        free(vd->wdname);
397 38097
                vd->wdname = VIN_n_Arg(arg);
398 38097
                if (vd->wdname == NULL)
399 0
                        return (vsm_diag(vd, "Invalid instance name: %s",
400 0
                            strerror(errno)));
401 38097
                break;
402
        default:
403 0
                return (vsm_diag(vd, "Unknown VSM_Arg('%c')", flag));
404
        }
405 38199
        return (1);
406 39015
}
407
408
/*--------------------------------------------------------------------*/
409
410
void
411 37791
VSM_Destroy(struct vsm **vdp)
412
{
413
        struct vsm *vd;
414
415 37791
        TAKE_OBJ_NOTNULL(vd, vdp, VSM_MAGIC);
416
417 37791
        VSM_ResetError(vd);
418 37791
        REPLACE(vd->wdname, NULL);
419 37791
        if (vd->diag != NULL)
420 0
                VSB_destroy(&vd->diag);
421 37791
        if (vd->wdfd >= 0)
422 37757
                closefd(&vd->wdfd);
423 37791
        vsm_delset(&vd->mgt);
424 37791
        vsm_delset(&vd->child);
425 37791
        FREE_OBJ(vd);
426 37791
}
427
428
/*--------------------------------------------------------------------*/
429
430
const char *
431 199
VSM_Error(const struct vsm *vd)
432
{
433
434 199
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
435
436 199
        if (vd->diag == NULL)
437 0
                return ("No VSM error");
438
        else
439 199
                return (VSB_data(vd->diag));
440 199
}
441
442
/*--------------------------------------------------------------------*/
443
444
void
445 76435
VSM_ResetError(struct vsm *vd)
446
{
447
448 76435
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
449
450 76435
        if (vd->diag == NULL)
451 75809
                return;
452 626
        VSB_destroy(&vd->diag);
453 76435
}
454
455
/*--------------------------------------------------------------------
456
 */
457
458
static int
459 290904
vsm_cmp_av(char * const *a1, char * const *a2)
460
{
461
462 429108
        while (1) {
463 429108
                if (*a1 == NULL && *a2 == NULL)
464 34038
                        return (0);
465 395070
                if (*a1 == NULL || *a2 == NULL)
466 14
                        return (1);
467 395070
                if (strcmp(*a1, *a2))
468 256866
                        return (1);
469 138204
                a1++;
470 138204
                a2++;
471
        }
472 290904
}
473
474
static struct vsm_seg *
475 35154
vsm_findcluster(const struct vsm_set *vs, const char *cnam)
476
{
477
        struct vsm_seg *vg;
478 35154
        AN(vs);
479 35154
        AN(cnam);
480 49836
        VTAILQ_FOREACH(vg, &vs->clusters, clist) {
481 49836
                AN(vg->av[1]);
482 49836
                if (!strcmp(cnam, vg->av[1]))
483 35154
                        return (vg);
484 14682
        }
485 0
        return (NULL);
486 35154
}
487
488
static unsigned
489 1041528
vsm_running(struct vsm_set *vs, pid_t pid)
490
{
491
492 1041528
        AN(vs);
493
494 1041528
        if (pid == 0)
495 0
                return (0);
496
497 1041528
        if (kill(pid, 0) == 0) {
498 1003125
                vs->couldkill = 1;
499 1003125
                return (1);
500
        }
501 38403
        if (errno == EPERM)     /* a process exists, assume running */
502 0
                return (1);
503 38403
        assert(errno != EINVAL);
504 38403
        return (0);
505 1041528
}
506
507
static int
508 63816
vsm_vlu_hash(struct vsm_set *vs, const char *line)
509
{
510
        int i;
511
        uintmax_t id1, id2;
512
513 63816
        i = sscanf(line, "# %ju %ju", &id1, &id2);
514 63816
        if (i != 2) {
515 0
                vs->retval |= vs->flag_restarted;
516 0
                return (0);
517
        }
518 63816
        if (vs->couldkill >= 0 && vsm_running(vs, id1)) {
519
                /* nothing to do */
520 63816
        } else if (vs->couldkill > 0 && errno == ESRCH) {
521 0
                vs->retval |= vs->flag_restarted | VSM_MGT_CHANGED;
522 0
                return (0);
523
        }
524 63816
        vs->retval |= VSM_MGT_RUNNING;
525 63816
        if (id1 != vs->id1 || id2 != vs->id2) {
526 63784
                vs->retval |= vs->flag_restarted;
527 63784
                vs->id1 = id1;
528 63784
                vs->id2 = id2;
529 63784
        }
530 63816
        return (0);
531 63816
}
532
533
static int
534 1336181
vsm_vlu_plus(struct vsm *vd, struct vsm_set *vs, const char *line)
535
{
536
        char **av;
537
        int ac;
538
        struct vsm_seg *vg;
539
540 1336181
        av = VAV_Parse(line + 1, &ac, 0);
541
542 1336181
        if (av[0] != NULL || ac < 4 || ac > 6) {
543 0
                (void)(vsm_diag(vd, "vsm_vlu_plus: bad index (%d/%s)",
544 0
                    ac, av[0]));
545 0
                VAV_Free(av);
546 0
                return (-1);
547
        }
548
549 1336181
        vg = vs->vg;
550 1336181
        CHECK_OBJ_ORNULL(vg, VSM_SEG_MAGIC);
551 1336181
        if (vg != NULL)
552 838
                AZ(vg->flags & VSM_FLAG_STALE);
553 1336504
        while (vg != NULL && vsm_cmp_av(&vg->av[1], &av[1]))
554 323
                vg = VTAILQ_NEXT(vg, list);
555 1336181
        if (vg != NULL) {
556
                /* entry compared equal, so it survives */
557 838
                CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
558 838
                VAV_Free(av);
559 838
                vg->flags |= VSM_FLAG_MARKSCAN;
560 838
                vs->vg = VTAILQ_NEXT(vg, list);
561 838
        } else {
562 1335343
                ALLOC_OBJ(vg, VSM_SEG_MAGIC);
563 1335343
                AN(vg);
564 1335343
                vg->av = av;
565 1335343
                vg->set = vs;
566 1335343
                vg->flags = VSM_FLAG_MARKSCAN;
567 1335343
                vg->serial = vd->serial;
568
569 1335343
                VTAILQ_INSERT_TAIL(&vs->segs, vg, list);
570 1335343
                if (ac == 4) {
571 32793
                        vg->flags |= VSM_FLAG_CLUSTER;
572 32793
                        VTAILQ_INSERT_TAIL(&vs->clusters, vg, clist);
573 1335343
                } else if (*vg->av[2] != '0') {
574 34255
                        vg->cluster = vsm_findcluster(vs, vg->av[1]);
575 34255
                        CHECK_OBJ_NOTNULL(vg->cluster, VSM_SEG_MAGIC);
576 34255
                }
577 1335343
                vs->retval |= vs->flag_changed;
578
        }
579 1336181
        return (0);
580 1336181
}
581
582
static int
583 33200
vsm_vlu_minus(struct vsm *vd, struct vsm_set *vs, const char *line)
584
{
585
        char **av;
586
        int ac;
587
        struct vsm_seg *vg;
588
589 33200
        av = VAV_Parse(line + 1, &ac, 0);
590
591 33200
        if (av[0] != NULL || ac < 4 || ac > 6) {
592 0
                (void)(vsm_diag(vd, "vsm_vlu_minus: bad index (%d/%s)",
593 0
                    ac, av[0]));
594 0
                VAV_Free(av);
595 0
                return (-1);
596
        }
597
598
        /* Clustered segments cannot come before their cluster */
599 33200
        if (*av[2] != '0')
600 899
                vg = vsm_findcluster(vs, av[1]);
601
        else
602 32301
                vg = VTAILQ_FIRST(&vs->segs);
603
604 289742
        for (;vg != NULL; vg = VTAILQ_NEXT(vg, list)) {
605 289742
                if (!vsm_cmp_av(&vg->av[1], &av[1])) {
606 33200
                        vs->retval |= vs->flag_changed;
607 33200
                        vsm_delseg(vg, 1);
608 33200
                        break;
609
                }
610 256542
        }
611 33200
        AN(vg);
612 33200
        VAV_Free(av);
613 33200
        return (0);
614 33200
}
615
616
static int v_matchproto_(vlu_f)
617 1433197
vsm_vlu_func(void *priv, const char *line)
618
{
619
        struct vsm *vd;
620
        struct vsm_set *vs;
621 1433197
        int i = 0;
622
623 1433197
        CAST_OBJ_NOTNULL(vs, priv, VSM_SET_MAGIC);
624 1433197
        vd = vs->vsm;
625 1433197
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
626 1433197
        AN(line);
627
628
        /* Up the serial counter. This wraps at UINTPTR_MAX/2
629
         * because thats the highest value we can store in struct
630
         * vsm_fantom. */
631 1433197
        vd->serial = VSM_PRIV_LOW(vd->serial + 1);
632
633 1433197
        switch (line[0]) {
634
        case '#':
635 63816
                i = vsm_vlu_hash(vs, line);
636 108767
                VTAILQ_FOREACH(vs->vg, &vs->segs, list)
637 44951
                        vs->vg->flags &= ~VSM_FLAG_MARKSCAN;
638 63816
                if (!(vs->retval & vs->flag_restarted))
639 32
                        vs->vg = VTAILQ_FIRST(&vs->segs);
640 63816
                break;
641
        case '+':
642 1336181
                i = vsm_vlu_plus(vd, vs, line);
643 1336181
                break;
644
        case '-':
645 33200
                i = vsm_vlu_minus(vd, vs, line);
646 33200
                break;
647
        default:
648 0
                break;
649
        }
650 1433197
        return (i);
651
}
652
653
static void
654 977705
vsm_readlines(struct vsm_set *vs)
655
{
656
        int i;
657
658 977705
        do {
659 1115492
                assert(vs->fd >= 0);
660 1115492
                i = VLU_Fd(vs->vlu, vs->fd);
661 1115492
        } while (!i);
662 977705
        assert(i == -2);
663 977705
}
664
665
static unsigned
666 1111958
vsm_refresh_set(struct vsm *vd, struct vsm_set *vs)
667
{
668 1111958
        unsigned restarted = 0;
669
        struct stat st;
670
671 1111958
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
672 1111958
        CHECK_OBJ_NOTNULL(vs, VSM_SET_MAGIC);
673 1111958
        vs->retval = 0;
674 2056772
        if (vs->dfd >= 0 && (
675 945821
            fstatat(vd->wdfd, vs->dname, &st, AT_SYMLINK_NOFOLLOW) ||
676 945832
            st.st_ino != vs->dst.st_ino ||
677 944813
            st.st_dev != vs->dst.st_dev ||
678 944814
            st.st_mode != vs->dst.st_mode ||
679 944814
            st.st_nlink == 0)) {
680 1042
                closefd(&vs->dfd);
681 1020
                restarted = vs->flag_restarted;
682 1020
        }
683
684 1111960
        if (vs->dfd < 0) {
685 167147
                if (vs->fd >= 0)
686 1017
                        closefd(&vs->fd);
687 167147
                vs->dfd = openat(vd->wdfd, vs->dname, O_RDONLY);
688 167147
        }
689
690 1111960
        if (vs->dfd < 0) {
691 103363
                vs->id1 = vs->id2 = 0;
692 103363
                vsm_wash_set(vs, 1);
693 103363
                return (vs->retval | restarted);
694
        }
695
696 1008597
        AZ(fstat(vs->dfd, &vs->dst));
697
698 1922493
        if (vs->fd >= 0 && (
699 929767
            fstatat(vs->dfd, "_.index", &st, AT_SYMLINK_NOFOLLOW) ||
700 913927
            st.st_ino != vs->fst.st_ino ||
701 913896
            st.st_dev != vs->fst.st_dev ||
702 913897
            st.st_mode != vs->fst.st_mode ||
703 913896
            st.st_size < vs->fst.st_size ||
704 913896
            st.st_nlink < 1)) {
705 15885
                closefd(&vs->fd);
706 15879
                vs->retval |= vs->flag_changed;
707 15879
        }
708
709 1008595
        if (vs->fd >= 0) {
710 913894
                vs->vg = NULL;
711 913894
                vsm_readlines(vs);
712 913894
        } else {
713 291971
                VTAILQ_FOREACH(vs->vg, &vs->segs, list)
714 197270
                        vs->vg->flags &= ~VSM_FLAG_MARKSCAN;
715 94701
                vs->vg = VTAILQ_FIRST(&vs->segs);
716 94701
                vs->fd = openat(vs->dfd, "_.index", O_RDONLY);
717 94701
                if (vs->fd < 0)
718 30885
                        return (vs->retval | restarted);
719 63816
                VLU_Reset(vs->vlu);
720 63816
                AZ(fstat(vs->fd, &vs->fst));
721 63816
                vsm_readlines(vs);
722 63816
                vsm_wash_set(vs, 0);
723
        }
724
725 977710
        vs->fst.st_size = lseek(vs->fd, 0L, SEEK_CUR);
726
727 977710
        if (vs->couldkill < 0 || vsm_running(vs, vs->id1))
728 939367
                vs->retval |= vs->flag_running;
729 977714
        return (vs->retval);
730 1111962
}
731
732
/*--------------------------------------------------------------------*/
733
734
unsigned
735 571402
VSM_Status(struct vsm *vd)
736
{
737 571402
        unsigned retval = 0;
738
        struct stat st;
739
740 571402
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
741
742
        /* See if the -n workdir changed */
743 571402
        if (vd->wdfd >= 0) {
744 532791
                AZ(fstat(vd->wdfd, &st));
745 1065581
                if (st.st_ino != vd->wdst.st_ino ||
746 532790
                    st.st_dev != vd->wdst.st_dev ||
747 532790
                    st.st_mode != vd->wdst.st_mode ||
748 532790
                    st.st_nlink == 0) {
749 2
                        closefd(&vd->wdfd);
750 0
                        vsm_wash_set(vd->mgt, 1);
751 0
                        vsm_wash_set(vd->child, 1);
752 0
                }
753 532789
        }
754
755
        /* Open workdir */
756 571400
        if (vd->wdfd < 0) {
757 38610
                retval |= VSM_MGT_RESTARTED | VSM_MGT_CHANGED;
758 38610
                retval |= VSM_WRK_RESTARTED | VSM_WRK_CHANGED;
759 38610
                vd->wdfd = open(vd->wdname, O_RDONLY);
760 38610
                if (vd->wdfd < 0)
761 581
                        (void)vsm_diag(vd,
762
                            "VSM_Status: Cannot open workdir");
763
                else
764 38029
                        AZ(fstat(vd->wdfd, &vd->wdst));
765 38610
        }
766
767 571400
        if (vd->wdfd >= 0) {
768 570828
                retval |= vsm_refresh_set(vd, vd->mgt);
769 570828
                if (vd->mgt->couldkill > 0 && (retval & VSM_MGT_RESTARTED))
770 38029
                        vd->mgt->couldkill = 0;
771 570828
                if (retval & VSM_MGT_RUNNING)
772 541129
                        retval |= vsm_refresh_set(vd, vd->child);
773 570828
                if (vd->child->couldkill > 0 && (retval & VSM_WRK_RESTARTED))
774 25703
                        vd->child->couldkill = 0;
775 570828
        }
776 571400
        return (retval);
777
}
778
779
/*--------------------------------------------------------------------*/
780
781
int
782 38097
VSM_Attach(struct vsm *vd, int progress)
783
{
784
        const char *def;
785
        double t0;
786
        unsigned u;
787 38097
        int i, n = 0;
788
789 38097
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
790
791 38097
        if (vd->patience < 0)
792 0
                t0 = DBL_MAX;
793
        else
794 38097
                t0 = VTIM_mono() + vd->patience;
795
796 38097
        if (vd->wdname == NULL) {
797 119
                def = getenv("VARNISH_DEFAULT_N");
798 119
                if (def == NULL)
799 0
                        def = ""; /* Use default (hostname) */
800 119
                i = VSM_Arg(vd, 'n', def);
801 119
                if (i < 0)
802 0
                        return (i);
803 119
                AN(vd->wdname);
804 119
        }
805
806 38097
        AZ(vd->attached);
807 38661
        while (!VSIG_int && !VSIG_term) {
808 38644
                u = VSM_Status(vd);
809 38644
                VSM_ResetError(vd);
810 38644
                if (u & VSM_MGT_RUNNING) {
811 38029
                        if (progress >= 0 && n > 4)
812 0
                                (void)write(progress, "\n", 1);
813 38029
                        vd->attached = 1;
814 38029
                        return (0);
815
                }
816 615
                if (t0 < VTIM_mono()) {
817 51
                        if (progress >= 0 && n > 4)
818 17
                                (void)write(progress, "\n", 1);
819 51
                        return (vsm_diag(vd,
820
                            "Could not get hold of varnishd, is it running?"));
821
                }
822 564
                if (progress >= 0 && !(++n % 4))
823 121
                        (void)write(progress, ".", 1);
824 564
                VTIM_sleep(.25);
825
        }
826 17
        return (vsm_diag(vd, "Attach interrupted"));
827 38097
}
828
829
/*--------------------------------------------------------------------*/
830
831
static struct vsm_seg *
832 102976
vsm_set_findseg(const struct vsm_set *vs, uintptr_t serial)
833
{
834
        struct vsm_seg *vg;
835
836 1297803
        VTAILQ_FOREACH(vg, &vs->segs, list) {
837 1235739
                if (vg->serial == serial)
838 40912
                        return (vg);
839 1194827
        }
840 117212
        VTAILQ_FOREACH(vg, &vs->stale, list) {
841 57405
                if (vg->serial == serial)
842 2257
                        return (vg);
843 55148
        }
844 59807
        return (NULL);
845 102976
}
846
847
static struct vsm_seg *
848 3354499
vsm_findseg(const struct vsm *vd, const struct vsm_fantom *vf)
849
{
850
        struct vsm_seg *vg;
851
        uint64_t x;
852
853 3354499
        x = VSM_PRIV_HIGH(vf->priv);
854 3354499
        if (x == vd->serial) {
855 3302337
                vg = (struct vsm_seg *)vf->priv2;
856 3302337
                if (!VALID_OBJ(vg, VSM_SEG_MAGIC) ||
857 3302337
                    vg->serial != VSM_PRIV_LOW(vf->priv))
858 0
                        WRONG("Corrupt fantom");
859 3302337
                return (vg);
860
        }
861
862 52162
        x = VSM_PRIV_LOW(vf->priv);
863 52162
        vg = vsm_set_findseg(vd->mgt, x);
864 52162
        if (vg == NULL)
865 50814
                vg = vsm_set_findseg(vd->child, x);
866 52162
        if (vg == NULL)
867 8993
                return (NULL);
868
869
        /* Update the fantom with the new priv so that lookups will be
870
         * fast on the next call. Note that this casts away the const. */
871 43169
        ((struct vsm_fantom *)TRUST_ME(vf))->priv =
872 43169
            VSM_PRIV_MERGE(vg->serial, vd->serial);
873 43169
        return (vg);
874 3354499
}
875
876
/*--------------------------------------------------------------------*/
877
878
void
879 144391
VSM__iter0(const struct vsm *vd, struct vsm_fantom *vf)
880
{
881
882 144391
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
883 144391
        AN(vf);
884
885 144391
        AN(vd->attached);
886 144391
        memset(vf, 0, sizeof *vf);
887 144391
}
888
889
int
890 1962832
VSM__itern(struct vsm *vd, struct vsm_fantom *vf)
891
{
892
        struct vsm_seg *vg;
893
894 1962832
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
895 1962832
        AN(vd->attached);
896 1962832
        AN(vf);
897
898 1962832
        if (vf->priv == 0) {
899 144390
                vg = VTAILQ_FIRST(&vd->mgt->segs);
900 144390
                if (vg == NULL)
901 2
                        return (0);
902 144388
        } else {
903 1818442
                vg = vsm_findseg(vd, vf);
904 1818442
                if (vg == NULL)
905 0
                        return (vsm_diag(vd, "VSM_FOREACH: inconsistency"));
906 1846568
                while (1) {
907 1846568
                        if (vg->set == vd->mgt && VTAILQ_NEXT(vg, list) == NULL)
908 142770
                                vg = VTAILQ_FIRST(&vd->child->segs);
909
                        else
910 1703798
                                vg = VTAILQ_NEXT(vg, list);
911 1846568
                        if (vg == NULL)
912 95245
                                return (0);
913 1751323
                        if (!(vg->flags & VSM_FLAG_CLUSTER))
914 1723197
                                break;
915
                }
916
        }
917 1867585
        memset(vf, 0, sizeof *vf);
918 1867585
        vf->priv = VSM_PRIV_MERGE(vg->serial, vd->serial);
919 1867585
        vf->priv2 = (uintptr_t)vg;
920 1867585
        vf->category = vg->av[4];
921 1867585
        vf->ident = vg->av[5];
922 1867585
        AN(vf->category);
923 1867585
        return (1);
924 1962832
}
925
926
/*--------------------------------------------------------------------*/
927
928
int
929 109326
VSM_Map(struct vsm *vd, struct vsm_fantom *vf)
930
{
931
        struct vsm_seg *vg, *vgc;
932
        size_t of, sz;
933
        int r;
934
935 109326
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
936 109326
        AN(vd->attached);
937 109326
        AN(vf);
938 109326
        vg = vsm_findseg(vd, vf);
939 109326
        if (vg == NULL)
940 0
                return (vsm_diag(vd, "VSM_Map: bad fantom"));
941
942 109326
        assert(vg->serial == VSM_PRIV_LOW(vf->priv));
943 109326
        assert(vg->av[4] == vf->category);
944 109326
        assert(vg->av[5] == vf->ident);
945
946 109326
        if (vg->b != NULL) {
947 0
                assert(vg->refs > 0);
948 0
                AN(vg->e);
949 0
                vf->b = vg->b;
950 0
                vf->e = vg->e;
951 0
                vg->refs++;
952 0
                return (0);
953
        }
954
955 109326
        assert(vg->refs == 0);
956
957 109326
        vgc = vg->cluster;
958
959 109326
        if (vgc == NULL) {
960 106871
                r = vsm_mapseg(vd, vg);
961 106871
                if (r)
962 12
                        return (r);
963 106859
                vf->b = vg->b;
964 106859
                vf->e = vg->e;
965
966 106859
                vg->refs++;
967
968 106859
                return (0);
969
        }
970
971 2455
        CHECK_OBJ_NOTNULL(vgc, VSM_SEG_MAGIC);
972 2455
        assert(vgc->flags & VSM_FLAG_CLUSTER);
973 2455
        assert(vg->s == NULL);
974 2455
        assert(vg->sz == 0);
975
976 2455
        r = vsm_mapseg(vd, vgc);
977 2455
        if (r)
978 0
                return (r);
979 2455
        vgc->refs++;
980
981 2455
        of = strtoul(vg->av[2], NULL, 10);
982 2455
        sz = strtoul(vg->av[3], NULL, 10);
983 2455
        assert(sz > 0);
984
985 2455
        assert(vgc->sz >= of + sz);
986 2455
        assert(vgc->s == vgc->b);
987 2455
        vg->b = (char *)vgc->b + of;
988 2455
        vg->e = (char *)vg->b + sz;
989
990 2455
        vf->b = vg->b;
991 2455
        vf->e = vg->e;
992
993 2455
        vg->refs++;
994
995 2455
        return (0);
996 109326
}
997
998
/*--------------------------------------------------------------------*/
999
1000
int
1001 96207
VSM_Unmap(struct vsm *vd, struct vsm_fantom *vf)
1002
{
1003
        struct vsm_seg *vg;
1004
1005 96207
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
1006 96207
        AN(vd->attached);
1007 96207
        AN(vf);
1008 96207
        AN(vf->b);
1009 96207
        vg = vsm_findseg(vd, vf);
1010 96207
        if (vg == NULL)
1011 0
                return (vsm_diag(vd, "VSM_Unmap: bad fantom"));
1012 96207
        CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
1013 96207
        assert(vg->refs > 0);
1014 96207
        vg->refs--;
1015 96207
        vf->b = NULL;
1016 96207
        vf->e = NULL;
1017 96207
        if (vg->refs > 0)
1018 0
                return (0);
1019
1020 96207
        if (vg->cluster) {
1021 500
                CHECK_OBJ_NOTNULL(vg->cluster, VSM_SEG_MAGIC);
1022 500
                assert(vg->s == NULL);
1023 500
                assert(vg->sz == 0);
1024 500
                assert(vg->cluster->refs > 0);
1025 500
                if (--vg->cluster->refs == 0) {
1026 466
                        vsm_unmapseg(vg->cluster);
1027 466
                        if (vg->cluster->flags & VSM_FLAG_STALE) {
1028 34
                                AN(vg->flags & VSM_FLAG_STALE);
1029 34
                                vsm_delseg(vg->cluster, 0);
1030 34
                        }
1031 466
                }
1032 500
                vg->b = vg->e = NULL;
1033 500
        } else {
1034 95707
                vsm_unmapseg(vg);
1035
        }
1036 96207
        if (vg->flags & VSM_FLAG_STALE)
1037 2257
                vsm_delseg(vg, 0);
1038 96207
        return (0);
1039 96207
}
1040
1041
/*--------------------------------------------------------------------*/
1042
1043
const struct vsm_valid *
1044 1330673
VSM_StillValid(const struct vsm *vd, const struct vsm_fantom *vf)
1045
{
1046
        struct vsm_seg *vg;
1047
1048 1330673
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
1049 1330673
        AN(vf);
1050 1330673
        vg = vsm_findseg(vd, vf);
1051 1330673
        if (vg == NULL || vg->flags & VSM_FLAG_STALE)
1052 11457
                return (VSM_invalid);
1053 1319216
        return (VSM_valid);
1054 1330673
}
1055
1056
/*--------------------------------------------------------------------*/
1057
1058
int
1059 120678
VSM_Get(struct vsm *vd, struct vsm_fantom *vf,
1060
    const char *category, const char *ident)
1061
{
1062
1063 120678
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
1064 120678
        AN(vd->attached);
1065 866302
        VSM_FOREACH(vf, vd) {
1066 793151
                if (strcmp(vf->category, category))
1067 745624
                        continue;
1068 47527
                if (ident != NULL && strcmp(vf->ident, ident))
1069 0
                        continue;
1070 47527
                return (1);
1071
        }
1072 73151
        memset(vf, 0, sizeof *vf);
1073 73151
        return (0);
1074 120678
}
1075
1076
/*--------------------------------------------------------------------*/
1077
1078
char *
1079 1615
VSM_Dup(struct vsm *vd, const char *category, const char *ident)
1080
{
1081
        struct vsm_fantom vf;
1082 1615
        char *p = NULL;
1083
1084 1615
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
1085 1615
        AN(vd->attached);
1086 6494
        VSM_FOREACH(&vf, vd) {
1087 6494
                if (strcmp(vf.category, category))
1088 2788
                        continue;
1089 3706
                if (ident != NULL && strcmp(vf.ident, ident))
1090 2091
                        continue;
1091 1615
                AZ(VSM_Map(vd, &vf));
1092 1615
                AN(vf.b);
1093 1615
                AN(vf.e);
1094 1615
                p = malloc((char*)vf.e - (char*)vf.b);
1095 1615
                AN(p);
1096 1615
                memcpy(p, vf.b, (char*)vf.e - (char*)vf.b);
1097 1615
                AZ(VSM_Unmap(vd, &vf));
1098 1615
                break;
1099
        }
1100 1615
        return (p);
1101
}