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 45
vsm_diag(struct vsm *vd, const char *fmt, ...)
161
{
162
        va_list ap;
163
164 45
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
165 45
        AN(fmt);
166
167 45
        if (vd->diag == NULL)
168 45
                vd->diag = VSB_new_auto();
169 45
        AN(vd->diag);
170 45
        VSB_clear(vd->diag);
171 45
        va_start(ap, fmt);
172 45
        VSB_vprintf(vd->diag, fmt, ap);
173 45
        va_end(ap);
174 45
        AZ(VSB_finish(vd->diag));
175 45
        return (-1);
176
}
177
178
/*--------------------------------------------------------------------*/
179
180
static int
181 6204
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 6204
        CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
189
190 6204
        if (vg->s != NULL)
191 100
                return (0);
192
193 6104
        ps = getpagesize();
194
195 6104
        of = strtoul(vg->av[2], NULL, 10);
196 6104
        off = RDN2(of, ps);
197
198 6104
        if (vg->flags & VSM_FLAG_CLUSTER)
199 43
                assert(of == 0);
200 6104
        assert(vg->cluster == NULL);
201
202 6104
        sz = strtoul(vg->av[3], NULL, 10);
203 6104
        assert(sz > 0);
204 6104
        assert(of >= off);
205 6104
        len = RUP2((of - off) + sz, ps);
206
207 6104
        vsb = VSB_new_auto();
208 6104
        AN(vsb);
209 6104
        VSB_printf(vsb, "%s/%s/%s", vd->wdname, vg->set->dname, vg->av[1]);
210 6104
        AZ(VSB_finish(vsb));
211
212 6104
        fd = open(VSB_data(vsb), O_RDONLY);     // XXX: openat
213 6104
        if (fd < 0) {
214 0
                VSB_destroy(&vsb);
215 0
                return (vsm_diag(vd, "Could not open segment"));
216
        }
217
218 12208
        s = (void*)mmap(NULL, len,
219
            PROT_READ,
220
            MAP_HASSEMAPHORE | MAP_NOSYNC | MAP_SHARED,
221 6104
            fd, (off_t)off);
222
223 6104
        VSB_destroy(&vsb);
224
225 6104
        closefd(&fd);
226 6104
        if (s == MAP_FAILED)
227 0
                return (vsm_diag(vd, "Could not mmap segment"));
228
229 6104
        vg->s = s;
230 6104
        vg->b = (char*)(vg->s) + of - off;
231 6104
        vg->e = (char *)vg->b + sz;
232 6104
        vg->sz = len;
233
234 6104
        return (0);
235 6204
}
236
237
static void
238 5448
vsm_unmapseg(struct vsm_seg *vg)
239
{
240
241 5448
        CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
242
243 5448
        AN(vg->b);
244 5448
        AN(vg->e);
245 5448
        AZ(munmap(vg->s, vg->sz));
246 5448
        vg->s = vg->b = vg->e = NULL;
247 5448
        vg->sz = 0;
248 5448
}
249
250
/*--------------------------------------------------------------------*/
251
252
static void
253 74723
vsm_delseg(struct vsm_seg *vg, int refsok)
254
{
255
256 74723
        CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
257
258 74723
        if (vg->set->vg == vg) {
259 4812
                AZ(vg->flags & VSM_FLAG_STALE);
260 4812
                vg->set->vg = VTAILQ_NEXT(vg, list);
261 4812
        }
262
263 74723
        if (refsok && vg->refs) {
264 133
                AZ(vg->flags & VSM_FLAG_STALE);
265 133
                vg->flags |= VSM_FLAG_STALE;
266 133
                VTAILQ_REMOVE(&vg->set->segs, vg, list);
267 133
                VTAILQ_INSERT_TAIL(&vg->set->stale, vg, list);
268 133
                return;
269
        }
270
271 74590
        if (vg->s != NULL)
272 0
                vsm_unmapseg(vg);
273
274 74590
        if (vg->flags & VSM_FLAG_CLUSTER) {
275 1865
                vg->flags &= ~VSM_FLAG_CLUSTER;
276 1865
                VTAILQ_REMOVE(&vg->set->clusters, vg, clist);
277 1865
        }
278
279 74590
        if (vg->flags & VSM_FLAG_STALE)
280 133
                VTAILQ_REMOVE(&vg->set->stale, vg, list);
281
        else
282 74457
                VTAILQ_REMOVE(&vg->set->segs, vg, list);
283 74590
        VAV_Free(vg->av);
284 74590
        FREE_OBJ(vg);
285 74723
}
286
287
/*--------------------------------------------------------------------*/
288
289
static struct vsm_set *
290 4420
vsm_newset(const char *dirname)
291
{
292
        struct vsm_set *vs;
293
294 4420
        ALLOC_OBJ(vs, VSM_SET_MAGIC);
295 4420
        AN(vs);
296 4420
        VTAILQ_INIT(&vs->segs);
297 4420
        VTAILQ_INIT(&vs->stale);
298 4420
        VTAILQ_INIT(&vs->clusters);
299 4420
        vs->dname = dirname;
300 4420
        vs->dfd = vs->fd = -1;
301 4420
        vs->vlu = VLU_New(vsm_vlu_func, vs, 0);
302 4420
        AN(vs->vlu);
303 4420
        if (getenv("VSM_NOPID") != NULL)
304 0
                vs->couldkill = -1;
305 4420
        return (vs);
306
}
307
308
static void
309 4364
vsm_delset(struct vsm_set **p)
310
{
311
        struct vsm_set *vs;
312
        struct vsm_seg *vg;
313
314 4364
        TAKE_OBJ_NOTNULL(vs, p, VSM_SET_MAGIC);
315
316 4364
        if (vs->fd >= 0)
317 2673
                closefd(&vs->fd);
318 4364
        if (vs->dfd >= 0)
319 3591
                closefd(&vs->dfd);
320 4364
        while ((vg = VTAILQ_FIRST(&vs->stale)) != NULL) {
321 0
                AN(vg->flags & VSM_FLAG_STALE);
322 0
                vsm_delseg(vg, 0);
323
        }
324 74680
        while ((vg = VTAILQ_FIRST(&vs->segs)) != NULL) {
325 70316
                AZ(vg->flags & VSM_FLAG_STALE);
326 70316
                vsm_delseg(vg, 0);
327
        }
328 4364
        assert(VTAILQ_EMPTY(&vs->clusters));
329 4364
        VLU_Destroy(&vs->vlu);
330 4364
        FREE_OBJ(vs);
331 4364
}
332
333
static void
334 9728
vsm_wash_set(const struct vsm_set *vs, int all)
335
{
336
        struct vsm_seg *vg, *vg2;
337
338 81865
        VTAILQ_FOREACH_SAFE(vg, &vs->segs, list, vg2) {
339 72137
                if (all || (vg->flags & VSM_FLAG_MARKSCAN) == 0)
340 2404
                        vsm_delseg(vg, 1);
341 72137
        }
342 9728
}
343
344
/*--------------------------------------------------------------------*/
345
346
struct vsm *
347 2210
VSM_New(void)
348
{
349
        struct vsm *vd;
350
351 2210
        ALLOC_OBJ(vd, VSM_MAGIC);
352 2210
        AN(vd);
353
354 2210
        vd->mgt = vsm_newset(VSM_MGT_DIRNAME);
355 2210
        vd->mgt->flag_running = VSM_MGT_RUNNING;
356 2210
        vd->mgt->flag_changed = VSM_MGT_CHANGED;
357 2210
        vd->mgt->flag_restarted = VSM_MGT_RESTARTED;
358
359 2210
        vd->child = vsm_newset(VSM_CHILD_DIRNAME);
360 2210
        vd->child->flag_running = VSM_WRK_RUNNING;
361 2210
        vd->child->flag_changed = VSM_WRK_CHANGED;
362 2210
        vd->child->flag_restarted = VSM_WRK_RESTARTED;
363
364 2210
        vd->mgt->vsm = vd;
365 2210
        vd->child->vsm = vd;
366 2210
        vd->wdfd = -1;
367 2210
        vd->patience = 5;
368 2210
        return (vd);
369
}
370
371
/*--------------------------------------------------------------------*/
372
373
int
374 2253
VSM_Arg(struct vsm *vd, char flag, const char *arg)
375
{
376 2253
        char *p = NULL;
377
378 2253
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
379
380 2253
        if (arg == NULL)
381 40
                return (1);
382 2213
        switch (flag) {
383
        case 't':
384 13
                if (!strcasecmp(arg, "off")) {
385 0
                        vd->patience = -1;
386 0
                } else {
387 13
                        vd->patience = strtod(arg, &p);
388 21
                        if ((p != NULL && *p != '\0') ||
389 8
                            !isfinite(vd->patience) || vd->patience < 0)
390 14
                                return (vsm_diag(vd,
391 7
                                    "-t: Invalid argument: %s", arg));
392
                }
393 6
                break;
394
        case 'n':
395 2200
                if (vd->wdname != NULL)
396 0
                        free(vd->wdname);
397 2200
                vd->wdname = VIN_n_Arg(arg);
398 2200
                if (vd->wdname == NULL)
399 0
                        return (vsm_diag(vd, "Invalid instance name: %s",
400 0
                            strerror(errno)));
401 2200
                break;
402
        default:
403 0
                return (vsm_diag(vd, "Unknown VSM_Arg('%c')", flag));
404
        }
405 2206
        return (1);
406 2253
}
407
408
/*--------------------------------------------------------------------*/
409
410
void
411 2182
VSM_Destroy(struct vsm **vdp)
412
{
413
        struct vsm *vd;
414
415 2182
        TAKE_OBJ_NOTNULL(vd, vdp, VSM_MAGIC);
416
417 2182
        VSM_ResetError(vd);
418 2182
        REPLACE(vd->wdname, NULL);
419 2182
        if (vd->diag != NULL)
420 0
                VSB_destroy(&vd->diag);
421 2182
        if (vd->wdfd >= 0)
422 2180
                closefd(&vd->wdfd);
423 2182
        vsm_delset(&vd->mgt);
424 2182
        vsm_delset(&vd->child);
425 2182
        FREE_OBJ(vd);
426 2182
}
427
428
/*--------------------------------------------------------------------*/
429
430
const char *
431 11
VSM_Error(const struct vsm *vd)
432
{
433
434 11
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
435
436 11
        if (vd->diag == NULL)
437 0
                return ("No VSM error");
438
        else
439 11
                return (VSB_data(vd->diag));
440 11
}
441
442
/*--------------------------------------------------------------------*/
443
444
void
445 4414
VSM_ResetError(struct vsm *vd)
446
{
447
448 4414
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
449
450 4414
        if (vd->diag == NULL)
451 4378
                return;
452 36
        VSB_destroy(&vd->diag);
453 4414
}
454
455
/*--------------------------------------------------------------------
456
 */
457
458
static int
459 16419
vsm_cmp_av(char * const *a1, char * const *a2)
460
{
461
462 24235
        while (1) {
463 24235
                if (*a1 == NULL && *a2 == NULL)
464 1920
                        return (0);
465 22315
                if (*a1 == NULL || *a2 == NULL)
466 0
                        return (1);
467 22315
                if (strcmp(*a1, *a2))
468 14499
                        return (1);
469 7816
                a1++;
470 7816
                a2++;
471
        }
472 16419
}
473
474
static struct vsm_seg *
475 2020
vsm_findcluster(const struct vsm_set *vs, const char *cnam)
476
{
477
        struct vsm_seg *vg;
478 2020
        AN(vs);
479 2020
        AN(cnam);
480 2787
        VTAILQ_FOREACH(vg, &vs->clusters, clist) {
481 2787
                AN(vg->av[1]);
482 2787
                if (!strcmp(cnam, vg->av[1]))
483 2020
                        return (vg);
484 767
        }
485 0
        return (NULL);
486 2020
}
487
488
static unsigned
489 60476
vsm_running(struct vsm_set *vs, pid_t pid)
490
{
491
492 60476
        AN(vs);
493
494 60476
        if (pid == 0)
495 0
                return (0);
496 60476
        assert(pid > 1);
497
498 60476
        if (kill(pid, 0) == 0) {
499 58356
                vs->couldkill = 1;
500 58356
                return (1);
501
        }
502 2120
        if (errno == EPERM)     /* a process exists, assume running */
503 0
                return (1);
504 2120
        assert(errno != EINVAL);
505 2120
        return (0);
506 60476
}
507
508
static int
509 3682
vsm_vlu_hash(struct vsm_set *vs, const char *line)
510
{
511
        int i;
512
        uintmax_t id1, id2;
513
514 3682
        i = sscanf(line, "# %ju %ju", &id1, &id2);
515 3682
        if (i != 2) {
516 0
                vs->retval |= vs->flag_restarted;
517 0
                return (0);
518
        }
519 3682
        if (vs->couldkill >= 0 && vsm_running(vs, id1)) {
520
                /* nothing to do */
521 3682
        } else if (vs->couldkill > 0 && errno == ESRCH) {
522 0
                vs->retval |= vs->flag_restarted | VSM_MGT_CHANGED;
523 0
                return (0);
524
        }
525 3682
        vs->retval |= VSM_MGT_RUNNING;
526 3682
        if (id1 != vs->id1 || id2 != vs->id2) {
527 3680
                vs->retval |= vs->flag_restarted;
528 3680
                vs->id1 = id1;
529 3680
                vs->id2 = id2;
530 3680
        }
531 3682
        return (0);
532 3682
}
533
534
static int
535 75507
vsm_vlu_plus(struct vsm *vd, struct vsm_set *vs, const char *line)
536
{
537
        char **av;
538
        int ac;
539
        struct vsm_seg *vg;
540
541 75507
        av = VAV_Parse(line + 1, &ac, 0);
542
543 75507
        if (av[0] != NULL || ac < 4 || ac > 6) {
544 0
                (void)(vsm_diag(vd, "vsm_vlu_plus: bad index (%d/%s)",
545 0
                    ac, av[0]));
546 0
                VAV_Free(av);
547 0
                return (-1);
548
        }
549
550 75507
        vg = vs->vg;
551 75507
        CHECK_OBJ_ORNULL(vg, VSM_SEG_MAGIC);
552 75507
        if (vg != NULL)
553 50
                AZ(vg->flags & VSM_FLAG_STALE);
554 75525
        while (vg != NULL && vsm_cmp_av(&vg->av[1], &av[1]))
555 18
                vg = VTAILQ_NEXT(vg, list);
556 75507
        if (vg != NULL) {
557
                /* entry compared equal, so it survives */
558 50
                CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
559 50
                VAV_Free(av);
560 50
                vg->flags |= VSM_FLAG_MARKSCAN;
561 50
                vs->vg = VTAILQ_NEXT(vg, list);
562 50
        } else {
563 75457
                ALLOC_OBJ(vg, VSM_SEG_MAGIC);
564 75457
                AN(vg);
565 75457
                vg->av = av;
566 75457
                vg->set = vs;
567 75457
                vg->flags = VSM_FLAG_MARKSCAN;
568 75457
                vg->serial = vd->serial;
569
570 75457
                VTAILQ_INSERT_TAIL(&vs->segs, vg, list);
571 75457
                if (ac == 4) {
572 1881
                        vg->flags |= VSM_FLAG_CLUSTER;
573 1881
                        VTAILQ_INSERT_TAIL(&vs->clusters, vg, clist);
574 75457
                } else if (*vg->av[2] != '0') {
575 1967
                        vg->cluster = vsm_findcluster(vs, vg->av[1]);
576 1967
                        CHECK_OBJ_NOTNULL(vg->cluster, VSM_SEG_MAGIC);
577 1967
                }
578 75457
                vs->retval |= vs->flag_changed;
579
        }
580 75507
        return (0);
581 75507
}
582
583
static int
584 1870
vsm_vlu_minus(struct vsm *vd, struct vsm_set *vs, const char *line)
585
{
586
        char **av;
587
        int ac;
588
        struct vsm_seg *vg;
589
590 1870
        av = VAV_Parse(line + 1, &ac, 0);
591
592 1870
        if (av[0] != NULL || ac < 4 || ac > 6) {
593 0
                (void)(vsm_diag(vd, "vsm_vlu_minus: bad index (%d/%s)",
594 0
                    ac, av[0]));
595 0
                VAV_Free(av);
596 0
                return (-1);
597
        }
598
599
        /* Clustered segments cannot come before their cluster */
600 1870
        if (*av[2] != '0')
601 53
                vg = vsm_findcluster(vs, av[1]);
602
        else
603 1817
                vg = VTAILQ_FIRST(&vs->segs);
604
605 16351
        for (;vg != NULL; vg = VTAILQ_NEXT(vg, list)) {
606 16351
                if (!vsm_cmp_av(&vg->av[1], &av[1])) {
607 1870
                        vs->retval |= vs->flag_changed;
608 1870
                        vsm_delseg(vg, 1);
609 1870
                        break;
610
                }
611 14481
        }
612 1870
        AN(vg);
613 1870
        VAV_Free(av);
614 1870
        return (0);
615 1870
}
616
617
static int v_matchproto_(vlu_f)
618 81059
vsm_vlu_func(void *priv, const char *line)
619
{
620
        struct vsm *vd;
621
        struct vsm_set *vs;
622 81059
        int i = 0;
623
624 81059
        CAST_OBJ_NOTNULL(vs, priv, VSM_SET_MAGIC);
625 81059
        vd = vs->vsm;
626 81059
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
627 81059
        AN(line);
628
629
        /* Up the serial counter. This wraps at UINTPTR_MAX/2
630
         * because thats the highest value we can store in struct
631
         * vsm_fantom. */
632 81059
        vd->serial = VSM_PRIV_LOW(vd->serial + 1);
633
634 81059
        switch (line[0]) {
635
        case '#':
636 3682
                i = vsm_vlu_hash(vs, line);
637 6136
                VTAILQ_FOREACH(vs->vg, &vs->segs, list)
638 2454
                        vs->vg->flags &= ~VSM_FLAG_MARKSCAN;
639 3682
                if (!(vs->retval & vs->flag_restarted))
640 2
                        vs->vg = VTAILQ_FIRST(&vs->segs);
641 3682
                break;
642
        case '+':
643 75507
                i = vsm_vlu_plus(vd, vs, line);
644 75507
                break;
645
        case '-':
646 1870
                i = vsm_vlu_minus(vd, vs, line);
647 1870
                break;
648
        default:
649 0
                break;
650
        }
651 81059
        return (i);
652
}
653
654
static void
655 56800
vsm_readlines(struct vsm_set *vs)
656
{
657
        int i;
658
659 56800
        do {
660 64682
                assert(vs->fd >= 0);
661 64682
                i = VLU_Fd(vs->vlu, vs->fd);
662 64682
        } while (!i);
663 56800
        assert(i == -2);
664 56800
}
665
666
static unsigned
667 64622
vsm_refresh_set(struct vsm *vd, struct vsm_set *vs)
668
{
669 64622
        unsigned restarted = 0;
670
        struct stat st;
671
672 64622
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
673 64622
        CHECK_OBJ_NOTNULL(vs, VSM_SET_MAGIC);
674 64622
        vs->retval = 0;
675 119519
        if (vs->dfd >= 0 && (
676 54952
            fstatat(vd->wdfd, vs->dname, &st, AT_SYMLINK_NOFOLLOW) ||
677 54953
            st.st_ino != vs->dst.st_ino ||
678 54897
            st.st_dev != vs->dst.st_dev ||
679 54897
            st.st_mode != vs->dst.st_mode ||
680 54897
            st.st_nlink == 0)) {
681 57
                closefd(&vs->dfd);
682 57
                restarted = vs->flag_restarted;
683 57
        }
684
685 64624
        if (vs->dfd < 0) {
686 9726
                if (vs->fd >= 0)
687 57
                        closefd(&vs->fd);
688 9726
                vs->dfd = openat(vd->wdfd, vs->dname, O_RDONLY);
689 9726
        }
690
691 64624
        if (vs->dfd < 0) {
692 6046
                vs->id1 = vs->id2 = 0;
693 6046
                vsm_wash_set(vs, 1);
694 6046
                return (vs->retval | restarted);
695
        }
696
697 58578
        AZ(fstat(vs->dfd, &vs->dst));
698
699 111699
        if (vs->fd >= 0 && (
700 54037
            fstatat(vs->dfd, "_.index", &st, AT_SYMLINK_NOFOLLOW) ||
701 53123
            st.st_ino != vs->fst.st_ino ||
702 53121
            st.st_dev != vs->fst.st_dev ||
703 53121
            st.st_mode != vs->fst.st_mode ||
704 53121
            st.st_size < vs->fst.st_size ||
705 53121
            st.st_nlink < 1)) {
706 920
                closefd(&vs->fd);
707 920
                vs->retval |= vs->flag_changed;
708 920
        }
709
710 58578
        if (vs->fd >= 0) {
711 53121
                vs->vg = NULL;
712 53121
                vsm_readlines(vs);
713 53121
        } else {
714 16667
                VTAILQ_FOREACH(vs->vg, &vs->segs, list)
715 11210
                        vs->vg->flags &= ~VSM_FLAG_MARKSCAN;
716 5457
                vs->vg = VTAILQ_FIRST(&vs->segs);
717 5457
                vs->fd = openat(vs->dfd, "_.index", O_RDONLY);
718 5457
                if (vs->fd < 0)
719 1775
                        return (vs->retval | restarted);
720 3682
                VLU_Reset(vs->vlu);
721 3682
                AZ(fstat(vs->fd, &vs->fst));
722 3682
                vsm_readlines(vs);
723 3682
                vsm_wash_set(vs, 0);
724
        }
725
726 56803
        vs->fst.st_size = lseek(vs->fd, 0L, SEEK_CUR);
727
728 56803
        if (vs->couldkill < 0 || vsm_running(vs, vs->id1))
729 54686
                vs->retval |= vs->flag_running;
730 56803
        return (vs->retval);
731 64624
}
732
733
/*--------------------------------------------------------------------*/
734
735
unsigned
736 33195
VSM_Status(struct vsm *vd)
737
{
738 33195
        unsigned retval = 0;
739
        struct stat st;
740
741 33195
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
742
743
        /* See if the -n workdir changed */
744 33195
        if (vd->wdfd >= 0) {
745 30969
                AZ(fstat(vd->wdfd, &st));
746 61936
                if (st.st_ino != vd->wdst.st_ino ||
747 30968
                    st.st_dev != vd->wdst.st_dev ||
748 30968
                    st.st_mode != vd->wdst.st_mode ||
749 30967
                    st.st_nlink == 0) {
750 2
                        closefd(&vd->wdfd);
751 0
                        vsm_wash_set(vd->mgt, 1);
752 0
                        vsm_wash_set(vd->child, 1);
753 0
                }
754 30967
        }
755
756
        /* Open workdir */
757 33193
        if (vd->wdfd < 0) {
758 2230
                retval |= VSM_MGT_RESTARTED | VSM_MGT_CHANGED;
759 2230
                retval |= VSM_WRK_RESTARTED | VSM_WRK_CHANGED;
760 2230
                vd->wdfd = open(vd->wdname, O_RDONLY);
761 2230
                if (vd->wdfd < 0)
762 34
                        (void)vsm_diag(vd,
763
                            "VSM_Status: Cannot open workdir");
764
                else
765 2196
                        AZ(fstat(vd->wdfd, &vd->wdst));
766 2230
        }
767
768 33193
        if (vd->wdfd >= 0) {
769 33164
                retval |= vsm_refresh_set(vd, vd->mgt);
770 33164
                if (vd->mgt->couldkill > 0 && (retval & VSM_MGT_RESTARTED))
771 2196
                        vd->mgt->couldkill = 0;
772 33164
                if (retval & VSM_MGT_RUNNING)
773 31458
                        retval |= vsm_refresh_set(vd, vd->child);
774 33164
                if (vd->child->couldkill > 0 && (retval & VSM_WRK_RESTARTED))
775 1481
                        vd->child->couldkill = 0;
776 33164
        }
777 33193
        return (retval);
778
}
779
780
/*--------------------------------------------------------------------*/
781
782
int
783 2200
VSM_Attach(struct vsm *vd, int progress)
784
{
785
        const char *def;
786
        double t0;
787
        unsigned u;
788 2200
        int i, n = 0;
789
790 2200
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
791
792 2200
        if (vd->patience < 0)
793 0
                t0 = DBL_MAX;
794
        else
795 2200
                t0 = VTIM_mono() + vd->patience;
796
797 2200
        if (vd->wdname == NULL) {
798 7
                def = getenv("VARNISH_DEFAULT_N");
799 7
                if (def == NULL)
800 0
                        def = ""; /* Use default (hostname) */
801 7
                i = VSM_Arg(vd, 'n', def);
802 7
                if (i < 0)
803 0
                        return (i);
804 7
                AN(vd->wdname);
805 7
        }
806
807 2200
        AZ(vd->attached);
808 2233
        while (!VSIG_int && !VSIG_term) {
809 2232
                u = VSM_Status(vd);
810 2232
                VSM_ResetError(vd);
811 2232
                if (u & VSM_MGT_RUNNING) {
812 2196
                        if (progress >= 0 && n > 4)
813 0
                                (void)write(progress, "\n", 1);
814 2196
                        vd->attached = 1;
815 2196
                        return (0);
816
                }
817 36
                if (t0 < VTIM_mono()) {
818 3
                        if (progress >= 0 && n > 4)
819 1
                                (void)write(progress, "\n", 1);
820 3
                        return (vsm_diag(vd,
821
                            "Could not get hold of varnishd, is it running?"));
822
                }
823 33
                if (progress >= 0 && !(++n % 4))
824 7
                        (void)write(progress, ".", 1);
825 33
                VTIM_sleep(.25);
826
        }
827 1
        return (vsm_diag(vd, "Attach interrupted"));
828 2200
}
829
830
/*--------------------------------------------------------------------*/
831
832
static struct vsm_seg *
833 5836
vsm_set_findseg(const struct vsm_set *vs, uintptr_t serial)
834
{
835
        struct vsm_seg *vg;
836
837 73255
        VTAILQ_FOREACH(vg, &vs->segs, list) {
838 69729
                if (vg->serial == serial)
839 2310
                        return (vg);
840 67419
        }
841 6629
        VTAILQ_FOREACH(vg, &vs->stale, list) {
842 3234
                if (vg->serial == serial)
843 131
                        return (vg);
844 3103
        }
845 3395
        return (NULL);
846 5836
}
847
848
static struct vsm_seg *
849 190369
vsm_findseg(const struct vsm *vd, const struct vsm_fantom *vf)
850
{
851
        struct vsm_seg *vg;
852
        uint64_t x;
853
854 190369
        x = VSM_PRIV_HIGH(vf->priv);
855 190369
        if (x == vd->serial) {
856 187411
                vg = (struct vsm_seg *)vf->priv2;
857 187411
                if (!VALID_OBJ(vg, VSM_SEG_MAGIC) ||
858 187411
                    vg->serial != VSM_PRIV_LOW(vf->priv))
859 0
                        WRONG("Corrupt fantom");
860 187411
                return (vg);
861
        }
862
863 2958
        x = VSM_PRIV_LOW(vf->priv);
864 2958
        vg = vsm_set_findseg(vd->mgt, x);
865 2958
        if (vg == NULL)
866 2878
                vg = vsm_set_findseg(vd->child, x);
867 2958
        if (vg == NULL)
868 517
                return (NULL);
869
870
        /* Update the fantom with the new priv so that lookups will be
871
         * fast on the next call. Note that this casts away the const. */
872 2441
        ((struct vsm_fantom *)TRUST_ME(vf))->priv =
873 2441
            VSM_PRIV_MERGE(vg->serial, vd->serial);
874 2441
        return (vg);
875 190369
}
876
877
/*--------------------------------------------------------------------*/
878
879
void
880 8346
VSM__iter0(const struct vsm *vd, struct vsm_fantom *vf)
881
{
882
883 8346
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
884 8346
        AN(vf);
885
886 8346
        AN(vd->attached);
887 8346
        memset(vf, 0, sizeof *vf);
888 8346
}
889
890
int
891 111697
VSM__itern(struct vsm *vd, struct vsm_fantom *vf)
892
{
893
        struct vsm_seg *vg;
894
895 111697
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
896 111697
        AN(vd->attached);
897 111697
        AN(vf);
898
899 111697
        if (vf->priv == 0) {
900 8346
                vg = VTAILQ_FIRST(&vd->mgt->segs);
901 8346
                if (vg == NULL)
902 0
                        return (0);
903 8346
        } else {
904 103351
                vg = vsm_findseg(vd, vf);
905 103351
                if (vg == NULL)
906 0
                        return (vsm_diag(vd, "VSM_FOREACH: inconsistency"));
907 104979
                while (1) {
908 104979
                        if (vg->set == vd->mgt && VTAILQ_NEXT(vg, list) == NULL)
909 8253
                                vg = VTAILQ_FIRST(&vd->child->segs);
910
                        else
911 96726
                                vg = VTAILQ_NEXT(vg, list);
912 104979
                        if (vg == NULL)
913 5568
                                return (0);
914 99411
                        if (!(vg->flags & VSM_FLAG_CLUSTER))
915 97783
                                break;
916
                }
917
        }
918 106129
        memset(vf, 0, sizeof *vf);
919 106129
        vf->priv = VSM_PRIV_MERGE(vg->serial, vd->serial);
920 106129
        vf->priv2 = (uintptr_t)vg;
921 106129
        vf->category = vg->av[4];
922 106129
        vf->ident = vg->av[5];
923 106129
        AN(vf->category);
924 106129
        return (1);
925 111697
}
926
927
/*--------------------------------------------------------------------*/
928
929
int
930 6204
VSM_Map(struct vsm *vd, struct vsm_fantom *vf)
931
{
932
        struct vsm_seg *vg, *vgc;
933
        size_t of, sz;
934
        int r;
935
936 6204
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
937 6204
        AN(vd->attached);
938 6204
        AN(vf);
939 6204
        vg = vsm_findseg(vd, vf);
940 6204
        if (vg == NULL)
941 0
                return (vsm_diag(vd, "VSM_Map: bad fantom"));
942
943 6204
        assert(vg->serial == VSM_PRIV_LOW(vf->priv));
944 6204
        assert(vg->av[4] == vf->category);
945 6204
        assert(vg->av[5] == vf->ident);
946
947 6204
        if (vg->b != NULL) {
948 0
                assert(vg->refs > 0);
949 0
                AN(vg->e);
950 0
                vf->b = vg->b;
951 0
                vf->e = vg->e;
952 0
                vg->refs++;
953 0
                return (0);
954
        }
955
956 6204
        assert(vg->refs == 0);
957
958 6204
        vgc = vg->cluster;
959
960 6204
        if (vgc == NULL) {
961 6061
                r = vsm_mapseg(vd, vg);
962 6061
                if (r)
963 0
                        return (r);
964 6061
                vf->b = vg->b;
965 6061
                vf->e = vg->e;
966
967 6061
                vg->refs++;
968
969 6061
                return (0);
970
        }
971
972 143
        CHECK_OBJ_NOTNULL(vgc, VSM_SEG_MAGIC);
973 143
        assert(vgc->flags & VSM_FLAG_CLUSTER);
974 143
        assert(vg->s == NULL);
975 143
        assert(vg->sz == 0);
976
977 143
        r = vsm_mapseg(vd, vgc);
978 143
        if (r)
979 0
                return (r);
980 143
        vgc->refs++;
981
982 143
        of = strtoul(vg->av[2], NULL, 10);
983 143
        sz = strtoul(vg->av[3], NULL, 10);
984 143
        assert(sz > 0);
985
986 143
        assert(vgc->sz >= of + sz);
987 143
        assert(vgc->s == vgc->b);
988 143
        vg->b = (char *)vgc->b + of;
989 143
        vg->e = (char *)vg->b + sz;
990
991 143
        vf->b = vg->b;
992 143
        vf->e = vg->e;
993
994 143
        vg->refs++;
995
996 143
        return (0);
997 6204
}
998
999
/*--------------------------------------------------------------------*/
1000
1001
int
1002 5449
VSM_Unmap(struct vsm *vd, struct vsm_fantom *vf)
1003
{
1004
        struct vsm_seg *vg;
1005
1006 5449
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
1007 5449
        AN(vd->attached);
1008 5449
        AN(vf);
1009 5449
        AN(vf->b);
1010 5449
        vg = vsm_findseg(vd, vf);
1011 5449
        if (vg == NULL)
1012 0
                return (vsm_diag(vd, "VSM_Unmap: bad fantom"));
1013 5449
        CHECK_OBJ_NOTNULL(vg, VSM_SEG_MAGIC);
1014 5449
        assert(vg->refs > 0);
1015 5449
        vg->refs--;
1016 5449
        vf->b = NULL;
1017 5449
        vf->e = NULL;
1018 5449
        if (vg->refs > 0)
1019 0
                return (0);
1020
1021 5449
        if (vg->cluster) {
1022 28
                CHECK_OBJ_NOTNULL(vg->cluster, VSM_SEG_MAGIC);
1023 28
                assert(vg->s == NULL);
1024 28
                assert(vg->sz == 0);
1025 28
                assert(vg->cluster->refs > 0);
1026 28
                if (--vg->cluster->refs == 0) {
1027 27
                        vsm_unmapseg(vg->cluster);
1028 27
                        if (vg->cluster->flags & VSM_FLAG_STALE) {
1029 2
                                AN(vg->flags & VSM_FLAG_STALE);
1030 2
                                vsm_delseg(vg->cluster, 0);
1031 2
                        }
1032 27
                }
1033 28
                vg->b = vg->e = NULL;
1034 28
        } else {
1035 5421
                vsm_unmapseg(vg);
1036
        }
1037 5449
        if (vg->flags & VSM_FLAG_STALE)
1038 131
                vsm_delseg(vg, 0);
1039 5449
        return (0);
1040 5449
}
1041
1042
/*--------------------------------------------------------------------*/
1043
1044
const struct vsm_valid *
1045 75373
VSM_StillValid(const struct vsm *vd, const struct vsm_fantom *vf)
1046
{
1047
        struct vsm_seg *vg;
1048
1049 75373
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
1050 75373
        AN(vf);
1051 75373
        vg = vsm_findseg(vd, vf);
1052 75373
        if (vg == NULL || vg->flags & VSM_FLAG_STALE)
1053 672
                return (VSM_invalid);
1054 74701
        return (VSM_valid);
1055 75373
}
1056
1057
/*--------------------------------------------------------------------*/
1058
1059
int
1060 6979
VSM_Get(struct vsm *vd, struct vsm_fantom *vf,
1061
    const char *category, const char *ident)
1062
{
1063
1064 6979
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
1065 6979
        AN(vd->attached);
1066 49957
        VSM_FOREACH(vf, vd) {
1067 45663
                if (strcmp(vf->category, category))
1068 42978
                        continue;
1069 2685
                if (ident != NULL && strcmp(vf->ident, ident))
1070 0
                        continue;
1071 2685
                return (1);
1072
        }
1073 4294
        memset(vf, 0, sizeof *vf);
1074 4294
        return (0);
1075 6979
}
1076
1077
/*--------------------------------------------------------------------*/
1078
1079
char *
1080 93
VSM_Dup(struct vsm *vd, const char *category, const char *ident)
1081
{
1082
        struct vsm_fantom vf;
1083 93
        char *p = NULL;
1084
1085 93
        CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
1086 93
        AN(vd->attached);
1087 373
        VSM_FOREACH(&vf, vd) {
1088 373
                if (strcmp(vf.category, category))
1089 160
                        continue;
1090 213
                if (ident != NULL && strcmp(vf.ident, ident))
1091 120
                        continue;
1092 93
                AZ(VSM_Map(vd, &vf));
1093 93
                AN(vf.b);
1094 93
                AN(vf.e);
1095 93
                p = malloc((char*)vf.e - (char*)vf.b);
1096 93
                AN(p);
1097 93
                memcpy(p, vf.b, (char*)vf.e - (char*)vf.b);
1098 93
                AZ(VSM_Unmap(vd, &vf));
1099 93
                break;
1100
        }
1101 93
        return (p);
1102
}