varnish-cache/bin/varnishd/storage/storage_malloc.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2011 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * Storage method based on malloc(3)
31
 */
32
33
#include "config.h"
34
35
#include "cache/cache_varnishd.h"
36
#include "common/heritage.h"
37
38
#include <stdio.h>
39
#include <stdlib.h>
40
41
#include "storage/storage.h"
42
#include "storage/storage_simple.h"
43
44
#include "vnum.h"
45
46
#include "VSC_sma.h"
47
48
struct sma_sc {
49
        unsigned                magic;
50
#define SMA_SC_MAGIC            0x1ac8a345
51
        struct lock             sma_mtx;
52
        VCL_BYTES               sma_max;
53
        VCL_BYTES               sma_alloc;
54
        struct VSC_sma          *stats;
55
};
56
57
struct sma {
58
        unsigned                magic;
59
#define SMA_MAGIC               0x69ae9bb9
60
        struct storage          s;
61
        size_t                  sz;
62
        struct sma_sc           *sc;
63
};
64
65
static struct VSC_lck *lck_sma;
66
67
static struct storage * v_matchproto_(sml_alloc_f)
68 238987
sma_alloc(const struct stevedore *st, size_t size)
69
{
70
        struct sma_sc *sma_sc;
71 238987
        struct sma *sma = NULL;
72
        void *p;
73
74 238987
        CAST_OBJ_NOTNULL(sma_sc, st->priv, SMA_SC_MAGIC);
75 238987
        Lck_Lock(&sma_sc->sma_mtx);
76 238987
        sma_sc->stats->c_req++;
77 238987
        if (sma_sc->sma_alloc + (VCL_BYTES)size > sma_sc->sma_max) {
78 6475
                sma_sc->stats->c_fail++;
79 6475
                size = 0;
80 6475
        } else {
81 232512
                sma_sc->sma_alloc += size;
82 232512
                sma_sc->stats->c_bytes += size;
83 232512
                sma_sc->stats->g_alloc++;
84 232512
                sma_sc->stats->g_bytes += size;
85 232512
                if (sma_sc->sma_max != VRT_INTEGER_MAX)
86 107360
                        sma_sc->stats->g_space -= size;
87
        }
88 238987
        Lck_Unlock(&sma_sc->sma_mtx);
89
90 238987
        if (size == 0)
91 6480
                return (NULL);
92
93
        /*
94
         * Do not collapse the sma allocation with sma->s.ptr: it is not
95
         * a good idea.  Not only would it make ->trim impossible,
96
         * performance-wise it would be a catastrophe with chunksized
97
         * allocations growing another full page, just to accommodate the sma.
98
         */
99
100 232507
        p = malloc(size);
101 232507
        if (p != NULL) {
102 232507
                ALLOC_OBJ(sma, SMA_MAGIC);
103 232507
                if (sma != NULL)
104 232507
                        sma->s.ptr = p;
105
                else
106 0
                        free(p);
107 232507
        }
108 232507
        if (sma == NULL) {
109 0
                Lck_Lock(&sma_sc->sma_mtx);
110
                /*
111
                 * XXX: Not nice to have counters go backwards, but we do
112
                 * XXX: Not want to pick up the lock twice just for stats.
113
                 */
114 0
                sma_sc->stats->c_fail++;
115 0
                sma_sc->sma_alloc -= size;
116 0
                sma_sc->stats->c_bytes -= size;
117 0
                sma_sc->stats->g_alloc--;
118 0
                sma_sc->stats->g_bytes -= size;
119 0
                if (sma_sc->sma_max != VRT_INTEGER_MAX)
120 0
                        sma_sc->stats->g_space += size;
121 0
                Lck_Unlock(&sma_sc->sma_mtx);
122 0
                return (NULL);
123
        }
124 232507
        sma->sc = sma_sc;
125 232507
        sma->sz = size;
126 232507
        sma->s.priv = sma;
127 232507
        sma->s.len = 0;
128 232507
        sma->s.space = size;
129 232507
        sma->s.magic = STORAGE_MAGIC;
130 232507
        return (&sma->s);
131 238987
}
132
133
static void v_matchproto_(sml_free_f)
134 161406
sma_free(struct storage *s)
135
{
136
        struct sma_sc *sma_sc;
137
        struct sma *sma;
138
139 161406
        CHECK_OBJ_NOTNULL(s, STORAGE_MAGIC);
140 161406
        CAST_OBJ_NOTNULL(sma, s->priv, SMA_MAGIC);
141 161406
        sma_sc = sma->sc;
142 161406
        assert(sma->sz == sma->s.space);
143 161406
        Lck_Lock(&sma_sc->sma_mtx);
144 161406
        sma_sc->sma_alloc -= sma->sz;
145 161406
        sma_sc->stats->g_alloc--;
146 161406
        sma_sc->stats->g_bytes -= sma->sz;
147 161406
        sma_sc->stats->c_freed += sma->sz;
148 161406
        if (sma_sc->sma_max != VRT_INTEGER_MAX)
149 39160
                sma_sc->stats->g_space += sma->sz;
150 161406
        Lck_Unlock(&sma_sc->sma_mtx);
151 161406
        free(sma->s.ptr);
152 161406
        FREE_OBJ(sma);
153 161406
}
154
155
static VCL_BYTES v_matchproto_(stv_var_used_space)
156 160
sma_used_space(const struct stevedore *st)
157
{
158
        struct sma_sc *sma_sc;
159
160 160
        CAST_OBJ_NOTNULL(sma_sc, st->priv, SMA_SC_MAGIC);
161 160
        return (sma_sc->sma_alloc);
162
}
163
164
static VCL_BYTES v_matchproto_(stv_var_free_space)
165 200
sma_free_space(const struct stevedore *st)
166
{
167
        struct sma_sc *sma_sc;
168
169 200
        CAST_OBJ_NOTNULL(sma_sc, st->priv, SMA_SC_MAGIC);
170 200
        return (sma_sc->sma_max - sma_sc->sma_alloc);
171
}
172
173
static void v_matchproto_(storage_init_f)
174 71940
sma_init(struct stevedore *parent, int ac, char * const *av)
175
{
176
        const char *e;
177
        uintmax_t u;
178
        struct sma_sc *sc;
179
180 71940
        ALLOC_OBJ(sc, SMA_SC_MAGIC);
181 71940
        AN(sc);
182 71940
        sc->sma_max = VRT_INTEGER_MAX;
183 71940
        assert(sc->sma_max == VRT_INTEGER_MAX);
184 71940
        parent->priv = sc;
185
186 71940
        AZ(av[ac]);
187 71940
        if (ac > 1)
188 0
                ARGV_ERR("(-s%s) too many arguments\n", parent->name);
189
190 71940
        if (ac == 0 || *av[0] == '\0')
191 36620
                 return;
192
193 35320
        e = VNUM_2bytes(av[0], &u, 0);
194 35320
        if (e != NULL)
195 0
                ARGV_ERR("(-s%s) size \"%s\": %s\n", parent->name, av[0], e);
196 35320
        if ((u != (uintmax_t)(size_t)u))
197 0
                ARGV_ERR("(-s%s) size \"%s\": too big\n", parent->name, av[0]);
198 35320
        if (u < 1024*1024)
199 0
                ARGV_ERR("(-s%s) size \"%s\": too small, "
200
                    "did you forget to specify M or G?\n", parent->name,
201
                    av[0]);
202
203 35320
        sc->sma_max = u;
204 71940
}
205
206
static void v_matchproto_(storage_open_f)
207 71841
sma_open(struct stevedore *st)
208
{
209
        struct sma_sc *sma_sc;
210
211 71841
        ASSERT_CLI();
212 71841
        st->lru = LRU_Alloc();
213 71841
        if (lck_sma == NULL)
214 36541
                lck_sma = Lck_CreateClass(NULL, "sma");
215 71841
        CAST_OBJ_NOTNULL(sma_sc, st->priv, SMA_SC_MAGIC);
216 71841
        Lck_New(&sma_sc->sma_mtx, lck_sma);
217 71841
        sma_sc->stats = VSC_sma_New(NULL, NULL, st->ident);
218 71841
        if (sma_sc->sma_max != VRT_INTEGER_MAX)
219 35320
                sma_sc->stats->g_space = sma_sc->sma_max;
220 71841
}
221
222
const struct stevedore sma_stevedore = {
223
        .magic          =       STEVEDORE_MAGIC,
224
        .name           =       "malloc",
225
        .init           =       sma_init,
226
        .open           =       sma_open,
227
        .sml_alloc      =       sma_alloc,
228
        .sml_free       =       sma_free,
229
        .allocobj       =       SML_allocobj,
230
        .panic          =       SML_panic,
231
        .methods        =       &SML_methods,
232
        .var_free_space =       sma_free_space,
233
        .var_used_space =       sma_used_space,
234
        .allocbuf       =       SML_AllocBuf,
235
        .freebuf        =       SML_FreeBuf,
236
};