[4.1] ea9e3aa Snapshot & refcount the final ban to check, to avoid running of the ban-list if the lurker washes this OC while we check it.
Martin Blix Grydeland
martin at varnish-software.com
Thu Mar 3 10:52:53 CET 2016
commit ea9e3aa324e9e491540ddcf846038778f4696613
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Mar 1 21:50:15 2016 +0000
Snapshot & refcount the final ban to check, to avoid running of the
ban-list if the lurker washes this OC while we check it.
Mostly diagnosed by: Martin
Fixes: #1864
diff --git a/bin/varnishd/cache/cache_ban.c b/bin/varnishd/cache/cache_ban.c
index 2838914..aea88e5 100644
--- a/bin/varnishd/cache/cache_ban.c
+++ b/bin/varnishd/cache/cache_ban.c
@@ -504,7 +504,7 @@ BAN_CheckObject(struct worker *wrk, struct objcore *oc, struct req *req)
{
struct ban *b;
struct vsl_log *vsl;
- struct ban * volatile b0;
+ struct ban *b0, *bn;
unsigned tests;
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
@@ -524,18 +524,23 @@ BAN_CheckObject(struct worker *wrk, struct objcore *oc, struct req *req)
/* If that fails, make a safe check */
Lck_Lock(&ban_mtx);
b0 = ban_start;
+ bn = oc->ban;
+ bn->refcount++;
Lck_Unlock(&ban_mtx);
- if (b0 == oc->ban)
+ AN(bn);
+
+ if (b0 == bn)
return (0);
+
/*
* This loop is safe without locks, because we know we hold
* a refcount on a ban somewhere in the list and we do not
* inspect the list past that ban.
*/
tests = 0;
- for (b = b0; b != oc->ban; b = VTAILQ_NEXT(b, list)) {
+ for (b = b0; b != bn; b = VTAILQ_NEXT(b, list)) {
CHECK_OBJ_NOTNULL(b, BAN_MAGIC);
if (b->flags & BANS_FLAG_COMPLETED)
continue;
@@ -544,6 +549,7 @@ BAN_CheckObject(struct worker *wrk, struct objcore *oc, struct req *req)
}
Lck_Lock(&ban_mtx);
+ bn->refcount--;
VSC_C_main->bans_tested++;
VSC_C_main->bans_tests_tested += tests;
diff --git a/bin/varnishd/cache/cache_ban_lurker.c b/bin/varnishd/cache/cache_ban_lurker.c
index 63371f8..b4bbc30 100644
--- a/bin/varnishd/cache/cache_ban_lurker.c
+++ b/bin/varnishd/cache/cache_ban_lurker.c
@@ -60,6 +60,7 @@ ban_cleantail(void)
Lck_Lock(&ban_mtx);
b = VTAILQ_LAST(&ban_head, banhead_s);
if (b != VTAILQ_FIRST(&ban_head) && b->refcount == 0) {
+ assert(VTAILQ_EMPTY(&b->objcore));
if (b->flags & BANS_FLAG_COMPLETED)
VSC_C_main->bans_completed--;
if (b->flags & BANS_FLAG_OBJ)
More information about the varnish-commit
mailing list