]> err.no Git - varnish/commitdiff
redo the purge.list function with proper locking
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Sun, 18 Jan 2009 14:26:32 +0000 (14:26 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Sun, 18 Jan 2009 14:26:32 +0000 (14:26 +0000)
git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3514 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache_ban.c

index 2db21feafc4e853f8131388e32d2d1f441a15265..1c0466d8bae506183346e950438a895a2de48050 100644 (file)
@@ -499,27 +499,30 @@ ccf_purge_hash(struct cli *cli, const char * const *av, void *priv)
 static void
 ccf_purge_list(struct cli *cli, const char * const *av, void *priv)
 {
-       struct ban *b0;
+       struct ban *b;
        struct ban_test *bt;
 
        (void)av;
        (void)priv;
-       /*
-        * XXX: Strictly speaking, this loop traversal is not lock-safe
-        * XXX: because we might inspect the last ban while it gets
-        * XXX: destroyed.  To properly fix this, we would need to either
-        * XXX: hold the lock over the entire loop, or grab refcounts
-        * XXX: under lock for each element of the list.
-        * XXX: We do neither, and hope for the best.
-        */
-       for (b0 = ban_start; b0 != NULL; b0 = VTAILQ_NEXT(b0, list)) {
-               if (b0->refcount == 0 && VTAILQ_NEXT(b0, list) == NULL)
-                       break;
-               VTAILQ_FOREACH(bt, &b0->tests, list)
-                       cli_out(cli, "%5u %d \"%s\"\n",
-                           b0->refcount, b0->flags,
-                           bt->test);
+
+       Lck_Lock(&ban_mtx);
+       VTAILQ_LAST(&ban_head, banhead)->refcount++;
+       Lck_Unlock(&ban_mtx);
+
+       VTAILQ_FOREACH(b, &ban_head, list) {
+               bt = VTAILQ_FIRST(&b->tests);
+               cli_out(cli, "%5u %4s\t%s\n",
+                   b->refcount, b->flags ? "Gone" : "", bt->test);
+               do {
+                       bt = VTAILQ_NEXT(bt, list);
+                       if (bt != NULL)
+                               cli_out(cli, "\t\t%s\n", bt->test);
+               } while (bt != NULL);
        }
+
+       Lck_Lock(&ban_mtx);
+       VTAILQ_LAST(&ban_head, banhead)->refcount--;
+       Lck_Unlock(&ban_mtx);
 }
 
 static struct cli_proto ban_cmds[] = {