[master] 58df714 The bans being washed by the ban-lurker can be overtaken by new duplicated bans while it runs.

Poul-Henning Kamp phk at FreeBSD.org
Thu Dec 12 16:59:12 CET 2013


commit 58df714a418ecf4144156971001938a9f8880257
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Thu Dec 12 15:58:26 2013 +0000

    The bans being washed by the ban-lurker can be overtaken by new
    duplicated bans while it runs.
    
    Stumbled on by:	scoof
    Fixes #1390

diff --git a/bin/varnishd/cache/cache_ban.c b/bin/varnishd/cache/cache_ban.c
index 70ed654..25274fd 100644
--- a/bin/varnishd/cache/cache_ban.c
+++ b/bin/varnishd/cache/cache_ban.c
@@ -1049,9 +1049,9 @@ ban_lurker_getfirst(struct vsl_log *vsl, struct ban *bt)
 
 static void
 ban_lurker_test_ban(struct worker *wrk, struct vsl_log *vsl, struct ban *bt,
-    const struct banhead_s *obans)
+    struct banhead_s *obans)
 {
-	struct ban *bl;
+	struct ban *bl, *bln;
 	struct objcore *oc;
 	struct object *o;
 	unsigned tests;
@@ -1076,7 +1076,12 @@ ban_lurker_test_ban(struct worker *wrk, struct vsl_log *vsl, struct ban *bt,
 		o = oc_getobj(&wrk->stats, oc);
 		CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
 		i = 0;
-		VTAILQ_FOREACH_REVERSE(bl, obans, banhead_s, l_list) {
+		VTAILQ_FOREACH_REVERSE_SAFE(bl, obans, banhead_s, l_list, bln) {
+			if (bl->flags & BANS_FLAG_COMPLETED) {
+				/* Ban was overtaken by new (dup) ban */
+				VTAILQ_REMOVE(obans, bl, l_list);
+				continue;
+			}
 			tests = 0;
 			i = ban_evaluate(bl->spec, o->http, NULL, &tests);
 			VSC_C_main->bans_lurker_tested++;
@@ -1101,16 +1106,10 @@ static int
 ban_lurker_work(struct worker *wrk, struct vsl_log *vsl)
 {
 	struct ban *b, *bt;
-	//struct objhead *oh;
-	// struct objcore *oc, *oc2;
-	//struct object *o;
 	struct banhead_s obans;
 	int i;
 
-	/*
-	 * Make a list of the bans we can do something about
-	 */
-
+	/* Make a list of the bans we can do something about */
 	VTAILQ_INIT(&obans);
 	Lck_Lock(&ban_mtx);
 	b = ban_start;
@@ -1141,7 +1140,9 @@ ban_lurker_work(struct worker *wrk, struct vsl_log *vsl)
 				VSLb(vsl, SLT_Debug,
 				    "Lurk bt completed %p", bt);
 			Lck_Lock(&ban_mtx);
-			ban_mark_completed(bt);
+			/* We can be raced by a new ban */
+			if (!(bt->flags & BANS_FLAG_COMPLETED))
+				ban_mark_completed(bt);
 			Lck_Unlock(&ban_mtx);
 			VTAILQ_REMOVE(&obans, bt, l_list);
 			if (VTAILQ_EMPTY(&obans))
@@ -1150,6 +1151,8 @@ ban_lurker_work(struct worker *wrk, struct vsl_log *vsl)
 		if (DO_DEBUG(DBG_LURKER))
 			VSLb(vsl, SLT_Debug, "Lurk bt %p", bt);
 		ban_lurker_test_ban(wrk, vsl, bt, &obans);
+		if (VTAILQ_EMPTY(&obans))
+			break;
 	}
 	return (1);
 }



More information about the varnish-commit mailing list