[master] 5dd54f8 ban lurker edge case: make sure we stop at the ban list tail

Nils Goroll nils.goroll at uplex.de
Tue Mar 6 16:57:07 UTC 2018


commit 5dd54f8390739c62c201e62c36eb515b1e03c2ee
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Tue Mar 6 16:03:50 2018 +0100

    ban lurker edge case: make sure we stop at the ban list tail
    
    in ban_lurker_test_ban() we remove completed bans from the obans list
    so the ban list tail might not be present in the obans list.
    
    To ensure that we stop at the tail, we now find our obans iteration
    termination ban walking the bans list backwards until we find an
    active ban, the head or the first obans element. In the latter two
    cases we are done.
    
    If there are any bans left to mark completed, the last active ban must
    be contained in the obans list so we should terminate correctly.
    
    Fixes #2556

diff --git a/bin/varnishd/cache/cache_ban_lurker.c b/bin/varnishd/cache/cache_ban_lurker.c
index 974cf9c..52a3c79 100644
--- a/bin/varnishd/cache/cache_ban_lurker.c
+++ b/bin/varnishd/cache/cache_ban_lurker.c
@@ -349,12 +349,30 @@ ban_lurker_work(struct worker *wrk, struct vsl_log *vsl)
 	if (ban_cleantail(VTAILQ_FIRST(&obans)))
 		return (dt);
 
+	if (VTAILQ_FIRST(&obans) == NULL)
+		return (dt);
+
 	/*
 	 * Mark remaining bans completed: the tail of the obans list is now
-	 * removed, but iterating over it is safe until we hit the new tail ban
+	 * removed, but iterating over it is safe until we hit the new ban list
+	 * tail
+	 *
+	 * bans at the tail of the list may have been completed by other means
+	 * and, consequently, may have been removed from obans, so we skip all
+	 * already completed bans at the tail.
+	 *
+	 * While traversing the ban list backwards, we check if we pass by the
+	 * first oban, in which case we're done.
 	 */
-	Lck_Lock(&ban_mtx);
 	bd = VTAILQ_LAST(&ban_head, banhead_s);
+	while (bd->flags & BANS_FLAG_COMPLETED) {
+		if (bd == VTAILQ_FIRST(&ban_head) ||
+		    bd == VTAILQ_FIRST(&obans))
+			return (dt);
+		bd = VTAILQ_PREV(bd, banhead_s, list);
+	}
+
+	Lck_Lock(&ban_mtx);
 	VTAILQ_FOREACH(b, &obans, l_list) {
 		ban_mark_completed(b);
 		if (b == bd)


More information about the varnish-commit mailing list