source: bin/varnishd/mgt_shmem.c @ 874655

Revision 874655, 7.5 KB checked in by Poul-Henning Kamp <phk@…>, 3 years ago (diff)

Get the rest of the stuff in there too.

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2011 Varnish Software AS
4 * All rights reserved.
5 *
6 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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 *
30 * TODO:
31 *
32 * There is a risk that the child process might corrupt the VSM segment
33 * and we should capture that event and recover gracefully.
34 *
35 * A possible state diagram could be:
36 *
37 *      [manager start]
38 *              |
39 *              v
40 *      Open old VSM,
41 *      check pid       --------> exit/fail (-n message)
42 *              |
43 *              +<----------------------+
44 *              |                       ^
45 *              v                       |
46 *      Create new VSM                  |
47 *              |                       |
48 *              v                       |
49 *      Init header                     |
50 *      Alloc VSL                       |
51 *      Alloc VSC:Main                  |
52 *      Alloc Args etc.                 |
53 *              |                       |
54 *              +<--------------+       |
55 *              |               ^       |
56 *              v               |       |
57 *      start worker            |       |
58 *              |               |       |
59 *              |               |       +<---- worker crash
60 *              v               |       ^
61 *      Reset VSL ptr.          |       |
62 *      Reset VSC counters      |       |
63 *              |               |       |
64 *              +<------+       |       |
65 *              |       ^       |       |
66 *              v       |       |       |
67 *      alloc dynamics  |       |       |
68 *      free dynamics   |       |       |
69 *              |       |       |       |
70 *              v       |       |       |
71 *              +------>+       |       |
72 *              |               |       |
73 *              v               |       |
74 *      stop worker             |       |
75 *              |               |       |
76 *              v               |       |
77 *      Check consist---------- | ----->+
78 *              |               |
79 *              v               |
80 *      Free dynamics           |
81 *              |               |
82 *              v               |
83 *              +-------------->+
84 *
85 */
86
87#include "config.h"
88
89#include "vapi/vsl_int.h"
90#include "vapi/vsc_int.h"
91
92#include <signal.h>
93#include <stdio.h>
94#include <stdlib.h>
95#include <unistd.h>
96#include <fcntl.h>
97#include <string.h>
98#include <sys/mman.h>
99#include <sys/stat.h>
100
101#include "mgt.h"
102#include "heritage.h"
103#include "vmb.h"
104#include "vapi/vsm_int.h"
105#include "vav.h"
106#include "vnum.h"
107#include "flopen.h"
108
109#ifndef MAP_HASSEMAPHORE
110#define MAP_HASSEMAPHORE 0 /* XXX Linux */
111#endif
112
113#ifndef MAP_NOSYNC
114#define MAP_NOSYNC 0 /* XXX Linux */
115#endif
116
117struct VSC_C_main       *VSC_C_main;
118
119static int vsl_fd = -1;
120
121/*--------------------------------------------------------------------
122 * Check that we are not started with the same -n argument as an already
123 * running varnishd
124 */
125
126static void
127vsl_n_check(int fd)
128{
129        struct VSM_head slh;
130        int i;
131        struct stat st;
132        pid_t pid;
133
134        AZ(fstat(fd, &st));
135        if (!S_ISREG(st.st_mode))
136                ARGV_ERR("\tshmlog: Not a file\n");
137
138        /* Test if the SHMFILE is locked by other Varnish */
139        if (fltest(fd, &pid) > 0) {
140                fprintf(stderr,
141                        "SHMFILE locked by running varnishd master (pid=%jd)\n",
142                        (intmax_t)pid);
143                fprintf(stderr,
144                        "(Use unique -n arguments if you want multiple "
145                        "instances)\n");
146                exit(2);
147        }
148
149        /* Read owning pid from SHMFILE */
150        memset(&slh, 0, sizeof slh);    /* XXX: for flexelint */
151        i = read(fd, &slh, sizeof slh);
152        if (i != sizeof slh)
153                return;
154        if (slh.magic != VSM_HEAD_MAGIC)
155                return;
156        if (slh.hdrsize != sizeof slh)
157                return;
158        if (slh.master_pid != 0 && !kill(slh.master_pid, 0)) {
159                fprintf(stderr,
160                        "WARNING: Taking over SHMFILE marked as owned by "
161                        "running process (pid=%jd)\n",
162                        (intmax_t)slh.master_pid);
163        }
164}
165
166/*--------------------------------------------------------------------
167 * Build a new shmlog file
168 */
169
170static void
171vsl_buildnew(const char *fn, unsigned size, int fill)
172{
173        struct VSM_head slh;
174        int i;
175        unsigned u;
176        char buf[64*1024];
177        int flags;
178
179        (void)unlink(fn);
180        vsl_fd = flopen(fn, O_RDWR | O_CREAT | O_EXCL | O_NONBLOCK, 0644);
181        if (vsl_fd < 0) {
182                fprintf(stderr, "Could not create %s: %s\n",
183                    fn, strerror(errno));
184                exit (1);
185        }
186        flags = fcntl(vsl_fd, F_GETFL);
187        assert(flags != -1);
188        flags &= ~O_NONBLOCK;
189        AZ(fcntl(vsl_fd, F_SETFL, flags));
190
191        memset(&slh, 0, sizeof slh);
192        slh.magic = VSM_HEAD_MAGIC;
193        slh.hdrsize = sizeof slh;
194        slh.shm_size = size;
195        i = write(vsl_fd, &slh, sizeof slh);
196        xxxassert(i == sizeof slh);
197
198        if (fill) {
199                memset(buf, 0, sizeof buf);
200                for (u = sizeof slh; u < size; ) {
201                        i = write(vsl_fd, buf, sizeof buf);
202                        if (i <= 0) {
203                                fprintf(stderr, "Write error %s: %s\n",
204                                    fn, strerror(errno));
205                                exit (1);
206                        }
207                        u += i;
208                }
209        }
210
211        AZ(ftruncate(vsl_fd, (off_t)size));
212}
213
214/*--------------------------------------------------------------------
215 * Exit handler that clears the owning pid from the SHMLOG
216 */
217
218static
219void
220mgt_shm_atexit(void)
221{
222        if (getpid() == VSM_head->master_pid)
223                VSM_head->master_pid = 0;
224}
225
226void
227mgt_SHM_Init(const char *l_arg)
228{
229        int i, fill;
230        struct params *pp;
231        const char *q;
232        uintmax_t size, s1, s2, ps;
233        char **av, **ap;
234        uint32_t *vsl_log_start;
235
236        if (l_arg == NULL)
237                l_arg = "";
238
239        av = VAV_Parse(l_arg, NULL, ARGV_COMMA);
240        AN(av);
241        if (av[0] != NULL)
242                ARGV_ERR("\t-l ...: %s", av[0]);
243
244        ap = av + 1;
245
246        /* Size of SHMLOG */
247        if (*ap != NULL && **ap != '\0') {
248                q = VNUM_2bytes(*ap, &s1, 0);
249                if (q != NULL)
250                        ARGV_ERR("\t-l[1] ...:  %s\n", q);
251        } else {
252                s1 = 80 * 1024 * 1024;
253        }
254        if (*ap != NULL)
255                ap++;
256
257        /* Size of space for other stuff */
258        if (*ap != NULL && **ap != '\0') {
259                q = VNUM_2bytes(*ap, &s2, 0);
260                if (q != NULL)
261                        ARGV_ERR("\t-l[2] ...:  %s\n", q);
262        } else {
263                s2 = 1024 * 1024;
264        }
265        if (*ap != NULL)
266                ap++;
267
268        /* Fill or not ? */
269        if (*ap != NULL) {
270                if (**ap == '\0')
271                        fill = 1;
272                else if (!strcmp(*ap, "-"))
273                        fill = 0;
274                else if (!strcmp(*ap, "+"))
275                        fill = 1;
276                else
277                        ARGV_ERR("\t-l[3] ...:  Must be \"-\" or \"+\"\n");
278                ap++;
279        } else {
280                fill = 1;
281        }
282
283        if (*ap != NULL)
284                ARGV_ERR("\t-l ...:  Too many sub-args\n");
285
286        VAV_Free(av);
287
288        size = s1 + s2;
289        ps = getpagesize();
290        size += ps - 1;
291        size &= ~(ps - 1);
292
293        i = open(VSM_FILENAME, O_RDWR, 0644);
294        if (i >= 0) {
295                vsl_n_check(i);
296                (void)close(i);
297        }
298        vsl_buildnew(VSM_FILENAME, size, fill);
299
300        VSM_head = (void *)mmap(NULL, size,
301            PROT_READ|PROT_WRITE,
302            MAP_HASSEMAPHORE | MAP_NOSYNC | MAP_SHARED,
303            vsl_fd, 0);
304        VSM_head->master_pid = getpid();
305        AZ(atexit(mgt_shm_atexit));
306        xxxassert(VSM_head != MAP_FAILED);
307        (void)mlock((void*)VSM_head, size);
308
309        memset(&VSM_head->head, 0, sizeof VSM_head->head);
310        VSM_head->head.magic = VSM_CHUNK_MAGIC;
311        VSM_head->head.len =
312            (uint8_t*)(VSM_head) + size - (uint8_t*)&VSM_head->head;
313        bprintf(VSM_head->head.class, "%s", VSM_CLASS_FREE);
314        VWMB();
315
316        vsm_end = (void*)((uint8_t*)VSM_head + size);
317
318        VSC_C_main = VSM_Alloc(sizeof *VSC_C_main,
319            VSC_CLASS, VSC_TYPE_MAIN, "");
320        AN(VSC_C_main);
321
322        pp = VSM_Alloc(sizeof *pp, VSM_CLASS_PARAM, "", "");
323        AN(pp);
324        *pp = *params;
325        params = pp;
326
327        vsl_log_start = VSM_Alloc(s1, VSL_CLASS, "", "");
328        AN(vsl_log_start);
329        vsl_log_start[1] = VSL_ENDMARKER;
330        VWMB();
331
332        do
333                *vsl_log_start = random() & 0xffff;
334        while (*vsl_log_start == 0);
335
336        VWMB();
337
338        do
339                VSM_head->alloc_seq = random();
340        while (VSM_head->alloc_seq == 0);
341
342}
343
344void
345mgt_SHM_Pid(void)
346{
347
348        VSM_head->master_pid = getpid();
349}
Note: See TracBrowser for help on using the repository browser.