[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