varnish-cache/bin/varnishd/cache/cache_hash.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
 *
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
 * This is the central hash-table code, it relies on a chosen hash
31
 * implementation only for the actual hashing, all the housekeeping
32
 * happens here.
33
 *
34
 * We have two kinds of structures, objecthead and object.  An objecthead
35
 * corresponds to a given (Host:, URL) tuple, and the objects hung from
36
 * the objecthead may represent various variations (ie: Vary: header,
37
 * different TTL etc) instances of that web-entity.
38
 *
39
 * Each objecthead has a mutex which locks both its own fields, the
40
 * list of objects and fields in the objects.
41
 *
42
 * The hash implementation must supply a reference count facility on
43
 * the objecthead, and return with a reference held after a lookup.
44
 *
45
 * Lookups in the hash implementation returns with a ref held and each
46
 * object hung from the objhead holds a ref as well.
47
 *
48
 * Objects have refcounts which are locked by the objecthead mutex.
49
 *
50
 * New objects are always marked busy, and they can go from busy to
51
 * not busy only once.
52
 */
53
54
#include "config.h"
55
56
#include <stdio.h>
57
#include <stdlib.h>
58
59
#include "cache_varnishd.h"
60
61
#include "cache/cache_objhead.h"
62
#include "cache/cache_transport.h"
63
64
#include "hash/hash_slinger.h"
65
66
#include "vsha256.h"
67
68
struct rush {
69
        unsigned                magic;
70
#define RUSH_MAGIC              0xa1af5f01
71
        VTAILQ_HEAD(,req)       reqs;
72
};
73
74
static const struct hash_slinger *hash;
75
#define PRIVATE_OH_EXP 7
76
static struct objhead private_ohs[1 << PRIVATE_OH_EXP];
77
78
static void hsh_rush1(const struct worker *, struct objhead *,
79
    struct rush *, int);
80
static void hsh_rush2(struct worker *, struct rush *);
81
static int hsh_deref_objhead(struct worker *wrk, struct objhead **poh);
82
static int hsh_deref_objhead_unlock(struct worker *wrk, struct objhead **poh,
83
    int);
84
85
/*---------------------------------------------------------------------*/
86
87
#define VCF_RETURN(x) const struct vcf_return VCF_##x[1] = { \
88
        { .name = #x, } \
89
};
90
91
VCF_RETURNS()
92
#undef VCF_RETURN
93
94
/*---------------------------------------------------------------------*/
95
96
static void
97 121623
hsh_initobjhead(struct objhead *oh)
98
{
99
100 121623
        XXXAN(oh);
101 121623
        INIT_OBJ(oh, OBJHEAD_MAGIC);
102 121623
        oh->refcnt = 1;
103 121623
        VTAILQ_INIT(&oh->objcs);
104 121623
        VTAILQ_INIT(&oh->waitinglist);
105 121623
        Lck_New(&oh->mtx, lck_objhdr);
106 121623
}
107
108
static struct objhead *
109 1559
hsh_newobjhead(void)
110
{
111 1559
        struct objhead *oh = malloc(sizeof *oh);
112 1559
        hsh_initobjhead(oh);
113 1559
        return (oh);
114
}
115
116
/*---------------------------------------------------------------------*/
117
/* Precreate an objhead and object for later use */
118
static void
119 2637
hsh_prealloc(struct worker *wrk)
120
{
121
122 2637
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
123
124 2637
        if (wrk->wpriv->nobjcore == NULL)
125 1780
                wrk->wpriv->nobjcore = ObjNew(wrk);
126 2637
        CHECK_OBJ_NOTNULL(wrk->wpriv->nobjcore, OBJCORE_MAGIC);
127
128 2637
        if (wrk->wpriv->nobjhead == NULL) {
129 1559
                wrk->wpriv->nobjhead = hsh_newobjhead();
130 1559
                wrk->stats->n_objecthead++;
131 1559
        }
132 2637
        CHECK_OBJ_NOTNULL(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
133
134 2637
        if (hash->prep != NULL)
135 2631
                hash->prep(wrk);
136 2637
}
137
138
/*---------------------------------------------------------------------*/
139
140
// https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
141
static inline size_t
142 1414
fib(uint64_t n, uint8_t bits)
143
{
144 1414
        const uint64_t gr = 11400714819323198485LLU;
145
        uint64_t r;
146
147 1414
        r = n * gr;
148 1414
        r >>= (sizeof(gr) * 8) - bits;
149 1414
        assert(r < (size_t)1 << bits);
150 1414
        return ((size_t)r);
151
}
152
153
struct objcore *
154 1414
HSH_Private(const struct worker *wrk)
155
{
156
        struct objcore *oc;
157
        struct objhead *oh;
158
159 1414
        oh = &private_ohs[fib((uintptr_t)wrk, PRIVATE_OH_EXP)];
160 1414
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
161
162 1414
        oc = ObjNew(wrk);
163 1414
        AN(oc);
164 1414
        oc->refcnt = 1;
165 1414
        oc->objhead = oh;
166 1414
        oc->flags |= OC_F_PRIVATE;
167 1414
        Lck_Lock(&oh->mtx);
168 1414
        VTAILQ_INSERT_TAIL(&oh->objcs, oc, hsh_list);
169 1414
        oh->refcnt++;
170 1414
        Lck_Unlock(&oh->mtx);
171 1414
        return (oc);
172
}
173
174
/*---------------------------------------------------------------------*/
175
176
void
177 947
HSH_Cleanup(const struct worker *wrk)
178
{
179
180 947
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
181 947
        CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
182 947
        if (wrk->wpriv->nobjcore != NULL)
183 2
                ObjDestroy(wrk, &wrk->wpriv->nobjcore);
184
185 947
        if (wrk->wpriv->nobjhead != NULL) {
186 2
                CHECK_OBJ(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
187 2
                Lck_Delete(&wrk->wpriv->nobjhead->mtx);
188 2
                FREE_OBJ(wrk->wpriv->nobjhead);
189 2
                wrk->stats->n_objecthead--;
190 2
        }
191 947
        if (wrk->wpriv->nhashpriv != NULL) {
192
                /* XXX: If needed, add slinger method for this */
193 2
                free(wrk->wpriv->nhashpriv);
194 2
                wrk->wpriv->nhashpriv = NULL;
195 2
        }
196 947
}
197
198
void
199 0
HSH_DeleteObjHead(const struct worker *wrk, struct objhead *oh)
200
{
201 0
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
202 0
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
203
204 0
        AZ(oh->refcnt);
205 0
        assert(VTAILQ_EMPTY(&oh->objcs));
206 0
        assert(VTAILQ_EMPTY(&oh->waitinglist));
207 0
        Lck_Delete(&oh->mtx);
208 0
        wrk->stats->n_objecthead--;
209 0
        FREE_OBJ(oh);
210 0
}
211
212
void
213 14656
HSH_AddString(struct req *req, void *ctx, const char *str)
214
{
215
216 14656
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
217 14656
        AN(ctx);
218 14656
        if (str != NULL) {
219 7327
                VSHA256_Update(ctx, str, strlen(str));
220 7327
                VSLbs(req->vsl, SLT_Hash, TOSTRAND(str));
221 7327
        } else
222 7329
                VSHA256_Update(ctx, &str, 1);
223 14656
}
224
225
/*---------------------------------------------------------------------
226
 * This is a debugging hack to enable testing of boundary conditions
227
 * in the hash algorithm.
228
 * We trap the first 9 different digests and translate them to different
229
 * digests with edge bit conditions
230
 */
231
232
static struct hsh_magiclist {
233
        unsigned char was[VSHA256_LEN];
234
        unsigned char now[VSHA256_LEN];
235
} hsh_magiclist[] = {
236
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
240
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } },
244
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } },
248
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 } },
252
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 } },
256
        { .now = {      0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
260
        { .now = {      0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
264
        { .now = {      0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
268
        { .now = {      0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
272
};
273
274
#define HSH_NMAGIC vcountof(hsh_magiclist)
275
276
static void
277 18
hsh_testmagic(void *result)
278
{
279
        size_t i, j;
280
        static size_t nused = 0;
281
282 90
        for (i = 0; i < nused; i++)
283 81
                if (!memcmp(hsh_magiclist[i].was, result, VSHA256_LEN))
284 9
                        break;
285 18
        if (i == nused && i < HSH_NMAGIC)
286 9
                memcpy(hsh_magiclist[nused++].was, result, VSHA256_LEN);
287 18
        if (i == nused)
288 0
                return;
289 18
        assert(i < HSH_NMAGIC);
290 18
        fprintf(stderr, "HASHMAGIC: <");
291 594
        for (j = 0; j < VSHA256_LEN; j++)
292 576
                fprintf(stderr, "%02x", ((unsigned char*)result)[j]);
293 18
        fprintf(stderr, "> -> <");
294 18
        memcpy(result, hsh_magiclist[i].now, VSHA256_LEN);
295 594
        for (j = 0; j < VSHA256_LEN; j++)
296 576
                fprintf(stderr, "%02x", ((unsigned char*)result)[j]);
297 18
        fprintf(stderr, ">\n");
298 18
}
299
300
/*---------------------------------------------------------------------
301
 * Insert an object which magically appears out of nowhere or, more likely,
302
 * comes off some persistent storage device.
303
 * Insert it with a reference held.
304
 */
305
306
void
307 17
HSH_Insert(struct worker *wrk, const void *digest, struct objcore *oc,
308
    struct ban *ban)
309
{
310
        struct objhead *oh;
311
        struct rush rush;
312
313 17
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
314 17
        CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
315 17
        AN(digest);
316 17
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
317 17
        AN(ban);
318 17
        AN(oc->flags & OC_F_BUSY);
319 17
        AZ(oc->flags & OC_F_PRIVATE);
320 17
        assert(oc->refcnt == 1);
321 17
        INIT_OBJ(&rush, RUSH_MAGIC);
322
323 17
        hsh_prealloc(wrk);
324
325 17
        AN(wrk->wpriv->nobjhead);
326 17
        oh = hash->lookup(wrk, digest, &wrk->wpriv->nobjhead);
327 17
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
328 17
        Lck_AssertHeld(&oh->mtx);
329 17
        assert(oh->refcnt > 0);
330
331
        /* Mark object busy and insert (precreated) objcore in
332
           objecthead. The new object inherits our objhead reference. */
333 17
        oc->objhead = oh;
334 17
        VTAILQ_INSERT_TAIL(&oh->objcs, oc, hsh_list);
335 17
        EXP_RefNewObjcore(oc);
336 17
        Lck_Unlock(&oh->mtx);
337
338 17
        BAN_RefBan(oc, ban);
339 17
        AN(oc->ban);
340
341
        /* Move the object first in the oh list, unbusy it and run the
342
           waitinglist if necessary */
343 17
        Lck_Lock(&oh->mtx);
344 17
        VTAILQ_REMOVE(&oh->objcs, oc, hsh_list);
345 17
        VTAILQ_INSERT_HEAD(&oh->objcs, oc, hsh_list);
346 17
        oc->flags &= ~OC_F_BUSY;
347 17
        if (!VTAILQ_EMPTY(&oh->waitinglist))
348 0
                hsh_rush1(wrk, oh, &rush, HSH_RUSH_POLICY);
349 17
        Lck_Unlock(&oh->mtx);
350 17
        hsh_rush2(wrk, &rush);
351
352 17
        EXP_Insert(wrk, oc);
353 17
}
354
355
/*---------------------------------------------------------------------
356
 */
357
358
static struct objcore *
359 1497
hsh_insert_busyobj(const struct worker *wrk, struct objhead *oh)
360
{
361
        struct objcore *oc;
362
363 1497
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
364 1497
        CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
365 1497
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
366 1497
        Lck_AssertHeld(&oh->mtx);
367
368 1497
        oc = wrk->wpriv->nobjcore;
369 1497
        wrk->wpriv->nobjcore = NULL;
370 1497
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
371
372 1497
        AN(oc->flags & OC_F_BUSY);
373 1497
        oc->refcnt = 1;         /* Owned by busyobj */
374 1497
        oc->objhead = oh;
375 1497
        VTAILQ_INSERT_TAIL(&oh->objcs, oc, hsh_list);
376 1497
        return (oc);
377
}
378
379
/*---------------------------------------------------------------------
380
 */
381
382
enum lookup_e
383 2620
HSH_Lookup(struct req *req, struct objcore **ocp, struct objcore **bocp)
384
{
385
        struct worker *wrk;
386
        struct objhead *oh;
387
        struct objcore *oc;
388
        struct objcore *exp_oc;
389
        const struct vcf_return *vr;
390
        vtim_real exp_t_origin;
391
        int busy_found;
392
        const uint8_t *vary;
393
        intmax_t boc_progress;
394 2620
        unsigned xid = 0;
395
        unsigned ban_checks;
396
        unsigned ban_any_variant;
397 2620
        float dttl = 0.0;
398
399 2620
        AN(ocp);
400 2620
        *ocp = NULL;
401 2620
        AN(bocp);
402 2620
        *bocp = NULL;
403
404 2620
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
405 2620
        wrk = req->wrk;
406 2620
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
407 2620
        CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
408 2620
        CHECK_OBJ_NOTNULL(req->http, HTTP_MAGIC);
409 2620
        CHECK_OBJ_ORNULL(req->vcf, VCF_MAGIC);
410 2620
        AN(hash);
411
412 2620
        hsh_prealloc(wrk);
413 2620
        if (DO_DEBUG(DBG_HASHEDGE))
414 18
                hsh_testmagic(req->digest);
415
416 2620
        if (req->hash_objhead != NULL) {
417
                /*
418
                 * This req came off the waiting list, and brings an
419
                 * oh refcnt with it.
420
                 */
421 49
                CHECK_OBJ_NOTNULL(req->hash_objhead, OBJHEAD_MAGIC);
422 49
                oh = req->hash_objhead;
423 49
                Lck_Lock(&oh->mtx);
424 49
                req->hash_objhead = NULL;
425 49
        } else {
426 2571
                AN(wrk->wpriv->nobjhead);
427 2571
                oh = hash->lookup(wrk, req->digest, &wrk->wpriv->nobjhead);
428
        }
429
430 2620
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
431 2620
        Lck_AssertHeld(&oh->mtx);
432
433 2620
        if (req->hash_always_miss) {
434
                /* XXX: should we do predictive Vary in this case ? */
435
                /* Insert new objcore in objecthead and release mutex */
436 14
                *bocp = hsh_insert_busyobj(wrk, oh);
437
                /* NB: no deref of objhead, new object inherits reference */
438 14
                Lck_Unlock(&oh->mtx);
439 14
                return (HSH_MISS);
440
        }
441
442 2606
        assert(oh->refcnt > 0);
443 2606
        busy_found = 0;
444 2606
        exp_oc = NULL;
445 2606
        exp_t_origin = 0.0;
446 2606
        ban_checks = 0;
447 2606
        ban_any_variant = cache_param->ban_any_variant;
448 5507
        VTAILQ_FOREACH(oc, &oh->objcs, hsh_list) {
449
                /* Must be at least our own ref + the objcore we examine */
450 4006
                assert(oh->refcnt > 1);
451 4006
                CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
452 4006
                assert(oc->objhead == oh);
453 4006
                assert(oc->refcnt > 0);
454
455 4006
                if (oc->flags & OC_F_DYING)
456 0
                        continue;
457 4006
                if (oc->flags & OC_F_FAILED)
458 0
                        continue;
459
460 4006
                CHECK_OBJ_ORNULL(oc->boc, BOC_MAGIC);
461 4006
                if (oc->flags & OC_F_BUSY) {
462 55
                        if (req->hash_ignore_busy)
463 1
                                continue;
464
465 56
                        if (oc->boc && oc->boc->vary != NULL &&
466 2
                            !req->hash_ignore_vary &&
467 2
                            !VRY_Match(req, oc->boc->vary)) {
468 1
                                wrk->strangelove++;
469 1
                                continue;
470
                        }
471
472 53
                        busy_found = 1;
473 53
                        continue;
474
                }
475
476 3951
                if (oc->ttl <= 0.)
477 46
                        continue;
478
479 3905
                if (ban_checks++ < ban_any_variant
480 3905
                    && BAN_CheckObject(wrk, oc, req)) {
481 0
                        oc->flags |= OC_F_DYING;
482 0
                        EXP_Remove(oc, NULL);
483 0
                        continue;
484
                }
485
486 3905
                if (!req->hash_ignore_vary && ObjHasAttr(wrk, oc, OA_VARY)) {
487 2820
                        vary = ObjGetAttr(wrk, oc, OA_VARY, NULL);
488 2820
                        AN(vary);
489 2820
                        if (!VRY_Match(req, vary)) {
490 2628
                                wrk->strangelove++;
491 2628
                                continue;
492
                        }
493 192
                }
494
495 1277
                if (ban_checks >= ban_any_variant
496 1277
                    && BAN_CheckObject(wrk, oc, req)) {
497 34
                        oc->flags |= OC_F_DYING;
498 34
                        EXP_Remove(oc, NULL);
499 34
                        continue;
500
                }
501
502 1243
                if (req->vcf != NULL) {
503 8
                        vr = req->vcf->func(req, &oc, &exp_oc, 0);
504 8
                        if (vr == VCF_CONTINUE)
505 4
                                continue;
506 4
                        if (vr == VCF_MISS) {
507 3
                                oc = NULL;
508 3
                                break;
509
                        }
510 1
                        if (vr == VCF_HIT)
511 1
                                break;
512 0
                        assert(vr == VCF_DEFAULT);
513 0
                }
514
515 1235
                if (EXP_Ttl(req, oc) > req->t_req) {
516 1101
                        assert(oh->refcnt > 1);
517 1101
                        assert(oc->objhead == oh);
518 1101
                        break;
519
                }
520
521 134
                if (EXP_Ttl(NULL, oc) <= req->t_req && /* ignore req.ttl */
522 131
                    oc->t_origin > exp_t_origin) {
523
                        /* record the newest object */
524 130
                        exp_oc = oc;
525 130
                        exp_t_origin = oc->t_origin;
526 130
                        assert(oh->refcnt > 1);
527 130
                        assert(exp_oc->objhead == oh);
528 130
                }
529 134
        }
530
531 2606
        if (req->vcf != NULL)
532 6
                (void)req->vcf->func(req, &oc, &exp_oc, 1);
533
534 2606
        if (oc != NULL && oc->flags & OC_F_HFP) {
535 11
                xid = VXID(ObjGetXID(wrk, oc));
536 11
                dttl = EXP_Dttl(req, oc);
537 11
                AN(hsh_deref_objhead_unlock(wrk, &oh, HSH_RUSH_POLICY));
538 11
                wrk->stats->cache_hitpass++;
539 11
                VSLb(req->vsl, SLT_HitPass, "%u %.6f", xid, dttl);
540 11
                return (HSH_HITPASS);
541
        }
542
543 2595
        if (oc != NULL) {
544 1092
                *ocp = oc;
545 1092
                oc->refcnt++;
546 1092
                if (oc->flags & OC_F_HFM) {
547 32
                        xid = VXID(ObjGetXID(wrk, oc));
548 32
                        dttl = EXP_Dttl(req, oc);
549 32
                        *bocp = hsh_insert_busyobj(wrk, oh);
550 32
                        Lck_Unlock(&oh->mtx);
551 32
                        wrk->stats->cache_hitmiss++;
552 32
                        VSLb(req->vsl, SLT_HitMiss, "%u %.6f", xid, dttl);
553 32
                        return (HSH_HITMISS);
554
                }
555 1060
                oc->hits++;
556 1060
                boc_progress = oc->boc == NULL ? -1 : oc->boc->fetched_so_far;
557 1060
                AN(hsh_deref_objhead_unlock(wrk, &oh, HSH_RUSH_POLICY));
558 1060
                Req_LogHit(wrk, req, oc, boc_progress);
559 1060
                return (HSH_HIT);
560
        }
561
562 1503
        if (exp_oc != NULL && exp_oc->flags & OC_F_HFM) {
563
                /*
564
                 * expired HFM ("grace/keep HFM")
565
                 *
566
                 * XXX should HFM objects actually have grace/keep ?
567
                 * XXX also:  why isn't *ocp = exp_oc ?
568
                 */
569 4
                xid = VXID(ObjGetXID(wrk, exp_oc));
570 4
                dttl = EXP_Dttl(req, exp_oc);
571 4
                *bocp = hsh_insert_busyobj(wrk, oh);
572 4
                Lck_Unlock(&oh->mtx);
573 4
                wrk->stats->cache_hitmiss++;
574 4
                VSLb(req->vsl, SLT_HitMiss, "%u %.6f", xid, dttl);
575 4
                return (HSH_HITMISS);
576
        }
577
578 1499
        if (exp_oc != NULL && exp_oc->boc != NULL)
579 4
                boc_progress = exp_oc->boc->fetched_so_far;
580
        else
581 1495
                boc_progress = -1;
582
583 1499
        if (!busy_found) {
584 1447
                *bocp = hsh_insert_busyobj(wrk, oh);
585
586 1447
                if (exp_oc != NULL) {
587 120
                        exp_oc->refcnt++;
588 120
                        *ocp = exp_oc;
589 120
                        if (EXP_Ttl_grace(req, exp_oc) >= req->t_req) {
590 92
                                exp_oc->hits++;
591 92
                                Lck_Unlock(&oh->mtx);
592 92
                                Req_LogHit(wrk, req, exp_oc, boc_progress);
593 92
                                return (HSH_GRACE);
594
                        }
595 28
                }
596 1355
                Lck_Unlock(&oh->mtx);
597 1355
                return (HSH_MISS);
598
        }
599
600 52
        AN(busy_found);
601 52
        if (exp_oc != NULL && EXP_Ttl_grace(req, exp_oc) >= req->t_req) {
602
                /* we do not wait on the busy object if in grace */
603 3
                exp_oc->refcnt++;
604 3
                *ocp = exp_oc;
605 3
                exp_oc->hits++;
606 3
                AN(hsh_deref_objhead_unlock(wrk, &oh, 0));
607 3
                Req_LogHit(wrk, req, exp_oc, boc_progress);
608 3
                return (HSH_GRACE);
609
        }
610
611
        /* There are one or more busy objects, wait for them */
612 49
        VTAILQ_INSERT_TAIL(&oh->waitinglist, req, w_list);
613
614 49
        AZ(req->hash_ignore_busy);
615
616
        /*
617
         * The objhead reference transfers to the sess, we get it
618
         * back when the sess comes off the waiting list and
619
         * calls us again
620
         */
621 49
        req->hash_objhead = oh;
622 49
        req->wrk = NULL;
623 49
        req->waitinglist = 1;
624
625 49
        if (DO_DEBUG(DBG_WAITINGLIST))
626 14
                VSLb(req->vsl, SLT_Debug, "on waiting list <%p>", oh);
627
628 49
        Lck_Unlock(&oh->mtx);
629
630 49
        wrk->stats->busy_sleep++;
631 49
        return (HSH_BUSY);
632 2620
}
633
634
/*---------------------------------------------------------------------
635
 * Pick the req's we are going to rush from the waiting list
636
 */
637
638
static void
639 38
hsh_rush1(const struct worker *wrk, struct objhead *oh, struct rush *r, int max)
640
{
641
        int i;
642
        struct req *req;
643
644 38
        if (max == 0)
645 2
                return;
646 36
        if (max == HSH_RUSH_POLICY)
647 36
                max = cache_param->rush_exponent;
648 36
        assert(max > 0);
649
650 36
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
651 36
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
652 36
        CHECK_OBJ_NOTNULL(r, RUSH_MAGIC);
653 36
        VTAILQ_INIT(&r->reqs);
654 36
        Lck_AssertHeld(&oh->mtx);
655 85
        for (i = 0; i < max; i++) {
656 77
                req = VTAILQ_FIRST(&oh->waitinglist);
657 77
                if (req == NULL)
658 28
                        break;
659 49
                CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
660 49
                wrk->stats->busy_wakeup++;
661 49
                AZ(req->wrk);
662 49
                VTAILQ_REMOVE(&oh->waitinglist, req, w_list);
663 49
                VTAILQ_INSERT_TAIL(&r->reqs, req, w_list);
664 49
                req->waitinglist = 0;
665 49
        }
666 38
}
667
668
/*---------------------------------------------------------------------
669
 * Rush req's that came from waiting list.
670
 */
671
672
static void
673 10781
hsh_rush2(struct worker *wrk, struct rush *r)
674
{
675
        struct req *req;
676
677 10781
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
678 10781
        CHECK_OBJ_NOTNULL(r, RUSH_MAGIC);
679
680 10830
        while (!VTAILQ_EMPTY(&r->reqs)) {
681 49
                req = VTAILQ_FIRST(&r->reqs);
682 49
                CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
683 49
                VTAILQ_REMOVE(&r->reqs, req, w_list);
684 49
                DSL(DBG_WAITINGLIST, req->vsl->wid, "off waiting list");
685 49
                if (req->transport->reembark != NULL) {
686
                        // For ESI includes
687 1
                        req->transport->reembark(wrk, req);
688 1
                } else {
689
                        /*
690
                         * We ignore the queue limits which apply to new
691
                         * requests because if we fail to reschedule there
692
                         * may be vmod_privs to cleanup and we need a proper
693
                         * workerthread for that.
694
                         */
695 48
                        AZ(Pool_Task(req->sp->pool, req->task, TASK_QUEUE_RUSH));
696
                }
697
        }
698 10781
}
699
700
/*---------------------------------------------------------------------
701
 * Purge an entire objhead
702
 */
703
704
unsigned
705 21
HSH_Purge(struct worker *wrk, struct objhead *oh, vtim_real ttl_now,
706
    vtim_dur ttl, vtim_dur grace, vtim_dur keep)
707
{
708
        struct objcore *oc, *oc_nows[2], **ocp;
709 21
        unsigned i, j, n, n_max, total = 0;
710
        int is_purge;
711
712 21
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
713 21
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
714
715 21
        is_purge = (ttl == 0 && grace == 0 && keep == 0);
716 21
        n_max = WS_ReserveLumps(wrk->aws, sizeof *ocp);
717 21
        if (n_max < 2) {
718
                /* No space on the workspace. Give it a stack buffer of 2
719
                 * elements, which is the minimum for the algorithm
720
                 * below. */
721 0
                ocp = oc_nows;
722 0
                n_max = 2;
723 0
        } else
724 21
                ocp = WS_Reservation(wrk->aws);
725 21
        AN(ocp);
726
727
        /* Note: This algorithm uses OC references in the list as
728
         * bookmarks, in order to know how far into the list we were when
729
         * releasing the mutex partway through and want to resume
730
         * again. This relies on the list not being reordered while we are
731
         * not holding the mutex. The only place where that happens is in
732
         * HSH_Unbusy(), where an OC_F_BUSY OC is moved first in the
733
         * list. This does not cause problems because we skip OC_F_BUSY
734
         * OCs. */
735
736 21
        Lck_Lock(&oh->mtx);
737 21
        oc = VTAILQ_FIRST(&oh->objcs);
738 21
        n = 0;
739 22
        while (1) {
740 130
                for (; n < n_max && oc != NULL; oc = VTAILQ_NEXT(oc, hsh_list))
741
                {
742 108
                        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
743 108
                        assert(oc->objhead == oh);
744 108
                        if (oc->flags & OC_F_BUSY) {
745
                                /* We cannot purge busy objects here, because
746
                                 * their owners have special rights to them,
747
                                 * and may nuke them without concern for the
748
                                 * refcount, which by definition always must
749
                                 * be one, so they don't check. */
750 17
                                continue;
751
                        }
752 91
                        if (oc->flags & OC_F_DYING)
753 0
                                continue;
754 91
                        if (is_purge)
755 81
                                oc->flags |= OC_F_DYING;
756 91
                        oc->refcnt++;
757 91
                        ocp[n++] = oc;
758 91
                }
759
760 22
                Lck_Unlock(&oh->mtx);
761
762 22
                if (n == 0) {
763
                        /* No eligible objcores found. We are finished. */
764 4
                        break;
765
                }
766
767 18
                j = n;
768 18
                if (oc != NULL) {
769
                        /* There are more objects on the objhead that we
770
                         * have not yet looked at, but no more space on
771
                         * the objcore reference list. Do not process the
772
                         * last one, it will be used as the bookmark into
773
                         * the objcore list for the next iteration of the
774
                         * outer loop. */
775 1
                        j--;
776 1
                        assert(j >= 1); /* True because n_max >= 2 */
777 1
                }
778 109
                for (i = 0; i < j; i++) {
779 91
                        CHECK_OBJ_NOTNULL(ocp[i], OBJCORE_MAGIC);
780 91
                        if (is_purge)
781 81
                                EXP_Remove(ocp[i], NULL);
782
                        else
783 10
                                EXP_Reduce(ocp[i], ttl_now, ttl, grace, keep);
784 91
                        (void)HSH_DerefObjCore(wrk, &ocp[i], 0);
785 91
                        AZ(ocp[i]);
786 91
                        total++;
787 91
                }
788
789 18
                if (j == n) {
790
                        /* No bookmark set, that means we got to the end
791
                         * of the objcore list in the previous run and are
792
                         * finished. */
793 17
                        break;
794
                }
795
796 1
                Lck_Lock(&oh->mtx);
797
798
                /* Move the bookmark first and continue scanning the
799
                 * objcores */
800 1
                CHECK_OBJ_NOTNULL(ocp[j], OBJCORE_MAGIC);
801 1
                ocp[0] = ocp[j];
802 1
                n = 1;
803 1
                oc = VTAILQ_NEXT(ocp[0], hsh_list);
804 1
                CHECK_OBJ_ORNULL(oc, OBJCORE_MAGIC);
805
        }
806
807 21
        WS_Release(wrk->aws, 0);
808 21
        if (is_purge)
809 11
                Pool_PurgeStat(total);
810 21
        return (total);
811
}
812
813
/*---------------------------------------------------------------------
814
 * Fail an objcore
815
 */
816
817
void
818 67
HSH_Fail(struct objcore *oc)
819
{
820
        struct objhead *oh;
821
822 67
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
823 67
        oh = oc->objhead;
824 67
        CHECK_OBJ(oh, OBJHEAD_MAGIC);
825
826
        /*
827
         * We have to have either a busy bit, so that HSH_Lookup
828
         * will not consider this oc, or an object hung of the oc
829
         * so that it can consider it.
830
         */
831 67
        assert((oc->flags & OC_F_BUSY) || (oc->stobj->stevedore != NULL));
832
833 67
        Lck_Lock(&oh->mtx);
834 67
        oc->flags |= OC_F_FAILED;
835 67
        Lck_Unlock(&oh->mtx);
836 67
}
837
838
/*---------------------------------------------------------------------
839
 * Mark a fetch we will not need as cancelled
840
 */
841
842
static void
843 353
hsh_cancel(struct objcore *oc)
844
{
845
        struct objhead *oh;
846
847 353
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
848 353
        oh = oc->objhead;
849 353
        CHECK_OBJ(oh, OBJHEAD_MAGIC);
850
851 353
        Lck_Lock(&oh->mtx);
852 353
        oc->flags |= OC_F_CANCEL;
853 353
        Lck_Unlock(&oh->mtx);
854 353
}
855
856
/*---------------------------------------------------------------------
857
 * Cancel a fetch when the client does not need it any more
858
 */
859
860
void
861 3803
HSH_Cancel(struct worker *wrk, struct objcore *oc, struct boc *boc)
862
{
863 3803
        struct boc *bocref = NULL;
864
865 3803
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
866
867 3803
        if ((oc->flags & OC_F_TRANSIENT) == 0)
868 2407
                return;
869
870
        /*
871
         * NB: we use two distinct variables to only release the reference if
872
         * we had to acquire one. The caller-provided boc is optional.
873
         */
874 1396
        if (boc == NULL)
875 1046
                bocref = boc = HSH_RefBoc(oc);
876
877 1396
        CHECK_OBJ_ORNULL(boc, BOC_MAGIC);
878
879 1396
        if (oc->flags & OC_F_HFP)
880 22
                AN(oc->flags & OC_F_HFM);
881
882 1396
        if (boc != NULL) {
883 353
                hsh_cancel(oc);
884 353
                ObjWaitState(oc, BOS_FINISHED);
885 353
        }
886
887 1396
        if (bocref != NULL)
888 3
                HSH_DerefBoc(wrk, oc);
889
890 1396
        ObjSlim(wrk, oc);
891 3803
}
892
893
/*---------------------------------------------------------------------
894
 * Unbusy an objcore when the object is completely fetched.
895
 */
896
897
void
898 2196
HSH_Unbusy(struct worker *wrk, struct objcore *oc)
899
{
900
        struct objhead *oh;
901
        struct rush rush;
902
903 2196
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
904 2196
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
905 2196
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
906
907 2196
        oh = oc->objhead;
908 2196
        CHECK_OBJ(oh, OBJHEAD_MAGIC);
909 2196
        INIT_OBJ(&rush, RUSH_MAGIC);
910
911 2196
        AN(oc->stobj->stevedore);
912 2196
        AN(oc->flags & OC_F_BUSY);
913 2196
        assert(oh->refcnt > 0);
914 2196
        assert(oc->refcnt > 0);
915
916 2196
        if (!(oc->flags & OC_F_PRIVATE)) {
917 1418
                BAN_NewObjCore(oc);
918 1418
                AN(oc->ban);
919 1418
        }
920
921
        /* XXX: pretouch neighbors on oh->objcs to prevent page-on under mtx */
922 2196
        Lck_Lock(&oh->mtx);
923 2196
        assert(oh->refcnt > 0);
924 2196
        assert(oc->refcnt > 0);
925 2196
        if (!(oc->flags & OC_F_PRIVATE))
926 1418
                EXP_RefNewObjcore(oc); /* Takes a ref for expiry */
927
        /* XXX: strictly speaking, we should sort in Date: order. */
928 2196
        VTAILQ_REMOVE(&oh->objcs, oc, hsh_list);
929 2196
        VTAILQ_INSERT_HEAD(&oh->objcs, oc, hsh_list);
930 2196
        oc->flags &= ~OC_F_BUSY;
931 2196
        if (!VTAILQ_EMPTY(&oh->waitinglist)) {
932 29
                assert(oh->refcnt > 1);
933 29
                hsh_rush1(wrk, oh, &rush, HSH_RUSH_POLICY);
934 29
        }
935 2196
        Lck_Unlock(&oh->mtx);
936 2196
        EXP_Insert(wrk, oc); /* Does nothing unless EXP_RefNewObjcore was
937
                              * called */
938 2196
        hsh_rush2(wrk, &rush);
939 2196
}
940
941
/*====================================================================
942
 * HSH_Kill()
943
 *
944
 * It's dead Jim, kick it...
945
 */
946
947
void
948 178
HSH_Kill(struct objcore *oc)
949
{
950
951 178
        HSH_Replace(oc, NULL);
952 178
}
953
954
void
955 249
HSH_Replace(struct objcore *oc, const struct objcore *new_oc)
956
{
957
958 249
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
959 249
        CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC);
960 249
        if (new_oc != NULL) {
961 71
                CHECK_OBJ(new_oc, OBJCORE_MAGIC);
962 71
                assert(oc->objhead == new_oc->objhead);
963 71
        }
964
965 249
        Lck_Lock(&oc->objhead->mtx);
966 249
        oc->flags |= OC_F_DYING;
967 249
        Lck_Unlock(&oc->objhead->mtx);
968 249
        EXP_Remove(oc, new_oc);
969 249
}
970
971
/*====================================================================
972
 * HSH_Snipe()
973
 *
974
 * If objcore is idle, gain a ref and mark it dead.
975
 */
976
977
int
978 11
HSH_Snipe(const struct worker *wrk, struct objcore *oc)
979
{
980 11
        int retval = 0;
981
982 11
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
983 11
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
984 11
        CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC);
985
986 11
        if (oc->refcnt == 1 && !Lck_Trylock(&oc->objhead->mtx)) {
987 11
                if (oc->refcnt == 1 && !(oc->flags & OC_F_DYING)) {
988 11
                        oc->flags |= OC_F_DYING;
989 11
                        oc->refcnt++;
990 11
                        retval = 1;
991 11
                }
992 11
                Lck_Unlock(&oc->objhead->mtx);
993 11
        }
994 11
        if (retval)
995 11
                EXP_Remove(oc, NULL);
996 11
        return (retval);
997
}
998
999
1000
/*---------------------------------------------------------------------
1001
 * Gain a reference on an objcore
1002
 */
1003
1004
void
1005 2415
HSH_Ref(struct objcore *oc)
1006
{
1007
        struct objhead *oh;
1008
1009 2415
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1010 2415
        oh = oc->objhead;
1011 2415
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
1012 2415
        Lck_Lock(&oh->mtx);
1013 2415
        assert(oc->refcnt > 0);
1014 2415
        oc->refcnt++;
1015 2415
        Lck_Unlock(&oh->mtx);
1016 2415
}
1017
1018
/*---------------------------------------------------------------------
1019
 * Gain a reference on the busyobj, if the objcore has one
1020
 */
1021
1022
struct boc *
1023 9495
HSH_RefBoc(const struct objcore *oc)
1024
{
1025
        struct objhead *oh;
1026
        struct boc *boc;
1027
1028 9495
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1029 9495
        oh = oc->objhead;
1030 9495
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
1031 9495
        if (oc->boc == NULL)
1032 5583
                return (NULL);
1033 3912
        Lck_Lock(&oh->mtx);
1034 3912
        assert(oc->refcnt > 0);
1035 3912
        boc = oc->boc;
1036 3912
        CHECK_OBJ_ORNULL(boc, BOC_MAGIC);
1037 3912
        if (boc != NULL) {
1038 3910
                assert(boc->refcount > 0);
1039 3910
                if (boc->state < BOS_FINISHED)
1040 3879
                        boc->refcount++;
1041
                else
1042 31
                        boc = NULL;
1043 3910
        }
1044 3912
        Lck_Unlock(&oh->mtx);
1045 3912
        return (boc);
1046 9495
}
1047
1048
void
1049 6772
HSH_DerefBoc(struct worker *wrk, struct objcore *oc)
1050
{
1051
        struct boc *boc;
1052
        unsigned r;
1053
1054 6772
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1055 6772
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1056 6772
        boc = oc->boc;
1057 6772
        CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
1058 6772
        Lck_Lock(&oc->objhead->mtx);
1059 6772
        assert(oc->refcnt > 0);
1060 6772
        assert(boc->refcount > 0);
1061 6772
        r = --boc->refcount;
1062 6772
        if (r == 0)
1063 2893
                oc->boc = NULL;
1064 6772
        Lck_Unlock(&oc->objhead->mtx);
1065 6772
        if (r == 0)
1066 2893
                ObjBocDone(wrk, oc, &boc);
1067 6772
}
1068
1069
/*--------------------------------------------------------------------
1070
 * Dereference objcore
1071
 *
1072
 * Returns zero if target was destroyed.
1073
 */
1074
1075
int
1076 7046
HSH_DerefObjCore(struct worker *wrk, struct objcore **ocp, int rushmax)
1077
{
1078
        struct objcore *oc;
1079
        struct objhead *oh;
1080
        struct rush rush;
1081
        int r;
1082
1083 7046
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1084 7046
        TAKE_OBJ_NOTNULL(oc, ocp, OBJCORE_MAGIC);
1085 7046
        assert(oc->refcnt > 0);
1086 7046
        INIT_OBJ(&rush, RUSH_MAGIC);
1087
1088 7046
        oh = oc->objhead;
1089 7046
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
1090
1091 7046
        Lck_Lock(&oh->mtx);
1092 7046
        assert(oh->refcnt > 0);
1093 7046
        r = --oc->refcnt;
1094 7046
        if (!r)
1095 1861
                VTAILQ_REMOVE(&oh->objcs, oc, hsh_list);
1096 7046
        if (!VTAILQ_EMPTY(&oh->waitinglist)) {
1097 3
                assert(oh->refcnt > 1);
1098 3
                hsh_rush1(wrk, oh, &rush, rushmax);
1099 3
        }
1100 7046
        Lck_Unlock(&oh->mtx);
1101 7046
        hsh_rush2(wrk, &rush);
1102 7046
        if (r != 0)
1103 5186
                return (r);
1104
1105 1860
        AZ(oc->exp_flags);
1106
1107 1860
        BAN_DestroyObj(oc);
1108 1860
        AZ(oc->ban);
1109
1110 1860
        if (oc->stobj->stevedore != NULL)
1111 1775
                ObjFreeObj(wrk, oc);
1112 1860
        ObjDestroy(wrk, &oc);
1113
1114
        /* Drop our ref on the objhead */
1115 1860
        assert(oh->refcnt > 0);
1116 1860
        (void)hsh_deref_objhead(wrk, &oh);
1117 1860
        return (0);
1118 7046
}
1119
1120
static int
1121 2935
hsh_deref_objhead_unlock(struct worker *wrk, struct objhead **poh, int max)
1122
{
1123
        struct objhead *oh;
1124
        struct rush rush;
1125
        int r;
1126
1127 2935
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1128 2935
        TAKE_OBJ_NOTNULL(oh, poh, OBJHEAD_MAGIC);
1129
1130 2935
        Lck_AssertHeld(&oh->mtx);
1131
1132 2935
        if (oh >= private_ohs && oh < private_ohs + vcountof(private_ohs)) {
1133 1414
                assert(VTAILQ_EMPTY(&oh->waitinglist));
1134 1414
                assert(oh->refcnt > 1);
1135 1414
                oh->refcnt--;
1136 1414
                Lck_Unlock(&oh->mtx);
1137 1414
                return (1);
1138
        }
1139
1140
        //lint --e{661}
1141
        //lint -specific(-e661)
1142
        //
1143
        // because of the static array, flexelint thinks that all ohs were from
1144
        // the static array :( the above suppression applies to the remainder of
1145
        // this function body and specific walks involving this function
1146
1147 1521
        INIT_OBJ(&rush, RUSH_MAGIC);
1148 1521
        if (!VTAILQ_EMPTY(&oh->waitinglist)) {
1149 6
                assert(oh->refcnt > 1);
1150 6
                hsh_rush1(wrk, oh, &rush, max);
1151 6
        }
1152
1153 1521
        if (oh->refcnt == 1)
1154 180
                assert(VTAILQ_EMPTY(&oh->waitinglist));
1155
1156 1521
        assert(oh->refcnt > 0);
1157 1521
        r = hash->deref(wrk, oh); /* Unlocks oh->mtx */
1158 1521
        hsh_rush2(wrk, &rush);
1159 1521
        return (r);
1160 2935
}
1161
1162
static int
1163 1860
hsh_deref_objhead(struct worker *wrk, struct objhead **poh)
1164
{
1165
        struct objhead *oh;
1166
1167 1860
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1168 1860
        TAKE_OBJ_NOTNULL(oh, poh, OBJHEAD_MAGIC);
1169
1170 1860
        Lck_Lock(&oh->mtx);
1171 1860
        return (hsh_deref_objhead_unlock(wrk, &oh, 0));
1172
}
1173
1174
void
1175 938
HSH_Init(const struct hash_slinger *slinger)
1176
{
1177
1178 938
        assert(DIGEST_LEN == VSHA256_LEN);      /* avoid #include pollution */
1179 938
        hash = slinger;
1180 938
        if (hash->start != NULL)
1181 938
                hash->start();
1182 121002
        for (struct objhead *oh = private_ohs;
1183 121002
            oh < private_ohs + vcountof(private_ohs);
1184 120064
            oh++) {
1185 120064
                hsh_initobjhead(oh);
1186 120064
                assert(oh->refcnt == 1);
1187 120064
        }
1188 938
}