[4.1] 365e605 Make param::nuke_limit a total count of nukes allowed for each object creation.
Martin Blix Grydeland
martin at varnish-software.com
Thu Jun 15 14:45:06 CEST 2017
commit 365e605627d2b383bcd440dcc0379ae503536a05
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Mon Feb 27 09:41:37 2017 +0000
Make param::nuke_limit a total count of nukes allowed for each
object creation.
Fixes #1764
Conflicts:
bin/varnishd/cache/cache_fetch.c
bin/varnishd/storage/stevedore.c
bin/varnishd/storage/storage.h
bin/varnishd/storage/storage_lru.c
bin/varnishd/storage/storage_persistent.c
bin/varnishd/storage/storage_simple.c
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index e63fdf0..7dfeff4 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -343,6 +343,7 @@ struct worker {
struct pool_task task;
double lastused;
+ int strangelove;
struct v1l *v1l;
diff --git a/bin/varnishd/cache/cache_expire.c b/bin/varnishd/cache/cache_expire.c
index 5c27d07..8a7c46b 100644
--- a/bin/varnishd/cache/cache_expire.c
+++ b/bin/varnishd/cache/cache_expire.c
@@ -329,6 +329,10 @@ EXP_NukeOne(struct worker *wrk, struct lru *lru)
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
+ if (wrk->strangelove-- <= 0) {
+ VSLb(wrk->vsl, SLT_ExpKill, "LRU_Exhausted");
+ return (0);
+ }
/* Find the first currently unused object on the LRU. */
Lck_Lock(&lru->mtx);
VTAILQ_FOREACH_SAFE(oc, &lru->lru_head, lru_list, oc2) {
diff --git a/bin/varnishd/cache/cache_obj.c b/bin/varnishd/cache/cache_obj.c
index edfd797..3c2eb01 100644
--- a/bin/varnishd/cache/cache_obj.c
+++ b/bin/varnishd/cache/cache_obj.c
@@ -239,7 +239,6 @@ objallocwithnuke(struct worker *wrk, const struct stevedore *stv,
size_t size, int flags)
{
struct storage *st = NULL;
- unsigned fail;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
@@ -252,18 +251,11 @@ objallocwithnuke(struct worker *wrk, const struct stevedore *stv,
assert(size <= UINT_MAX); /* field limit in struct storage */
- for (fail = 0; fail <= cache_param->nuke_limit; fail++) {
- /* try to allocate from it */
- AN(stv->alloc);
+ AN(stv->alloc);
+ do {
st = STV_alloc(stv, size, flags);
- if (st != NULL)
- break;
+ } while (st == NULL && EXP_NukeOne(wrk, stv->lru) == 1);
- /* no luck; try to free some space and keep trying */
- if (fail < cache_param->nuke_limit &&
- EXP_NukeOne(wrk, stv->lru) == -1)
- break;
- }
CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
return (st);
}
diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c
index 4845dba..d53b845 100644
--- a/bin/varnishd/storage/stevedore.c
+++ b/bin/varnishd/storage/stevedore.c
@@ -259,13 +259,15 @@ STV_NewObject(struct objcore *oc, struct worker *wrk,
const char *hint, unsigned wsl)
{
struct stevedore *stv, *stv0;
- int i, j;
+ int j;
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
assert(wsl > 0);
+ wrk->strangelove = cache_param->nuke_limit;
stv = stv0 = stv_pick_stevedore(wrk->vsl, &hint);
+ AN(stv);
AN(stv->allocobj);
j = stv->allocobj(stv, oc, wsl);
if (j == 0 && hint == NULL) {
@@ -275,15 +277,12 @@ STV_NewObject(struct objcore *oc, struct worker *wrk,
j = stv->allocobj(stv, oc, wsl);
} while (j == 0 && stv != stv0);
}
- if (j == 0) {
+ while (j == 0) {
/* no luck; try to free some space and keep trying */
- for (i = 0; j == 0 && i < cache_param->nuke_limit; i++) {
- if (EXP_NukeOne(wrk, stv->lru) == -1)
- break;
- j = stv->allocobj(stv, oc, wsl);
- }
+ if (EXP_NukeOne(wrk, stv->lru) != 1)
+ break;
+ j = stv->allocobj(stv, oc, wsl);
}
-
if (j == 0)
return (0);
diff --git a/bin/varnishtest/tests/r01764.vtc b/bin/varnishtest/tests/r01764.vtc
new file mode 100644
index 0000000..ba428ef
--- /dev/null
+++ b/bin/varnishtest/tests/r01764.vtc
@@ -0,0 +1,53 @@
+varnishtest "Test nuke_limit"
+
+server s1 {
+ # First consume (almost) all of the storage
+ rxreq
+ expect req.url == /url1
+ txresp -bodylen 200000
+
+ rxreq
+ expect req.url == /url2
+ txresp -bodylen 200000
+
+ rxreq
+ expect req.url == /url3
+ txresp -bodylen 200000
+
+ rxreq
+ expect req.url == /url4
+ txresp -bodylen 200000
+
+ rxreq
+ expect req.url == /url5
+ txresp -bodylen 1000000
+} -start
+
+varnish v1 -arg "-smalloc,1M" -arg "-p nuke_limit=1" -vcl+backend {
+ sub vcl_backend_response {
+ set beresp.do_stream = false;
+ }
+} -start
+
+
+client c1 {
+ txreq -url /url1
+ rxresp
+ expect resp.status == 200
+
+ txreq -url /url2
+ rxresp
+ expect resp.status == 200
+
+ txreq -url /url3
+ rxresp
+ expect resp.status == 200
+
+ txreq -url /url4
+ rxresp
+ expect resp.status == 200
+
+ txreq -url /url5
+ rxresp
+ expect resp.status == 503
+} -run
More information about the varnish-commit
mailing list