Commit 365e6056 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp Committed by Martin Blix Grydeland

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
parent 68f15e0e
...@@ -343,6 +343,7 @@ struct worker { ...@@ -343,6 +343,7 @@ struct worker {
struct pool_task task; struct pool_task task;
double lastused; double lastused;
int strangelove;
struct v1l *v1l; struct v1l *v1l;
......
...@@ -329,6 +329,10 @@ EXP_NukeOne(struct worker *wrk, struct lru *lru) ...@@ -329,6 +329,10 @@ EXP_NukeOne(struct worker *wrk, struct lru *lru)
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(lru, LRU_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. */ /* Find the first currently unused object on the LRU. */
Lck_Lock(&lru->mtx); Lck_Lock(&lru->mtx);
VTAILQ_FOREACH_SAFE(oc, &lru->lru_head, lru_list, oc2) { VTAILQ_FOREACH_SAFE(oc, &lru->lru_head, lru_list, oc2) {
......
...@@ -239,7 +239,6 @@ objallocwithnuke(struct worker *wrk, const struct stevedore *stv, ...@@ -239,7 +239,6 @@ objallocwithnuke(struct worker *wrk, const struct stevedore *stv,
size_t size, int flags) size_t size, int flags)
{ {
struct storage *st = NULL; struct storage *st = NULL;
unsigned fail;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC); CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
...@@ -252,18 +251,11 @@ objallocwithnuke(struct worker *wrk, const struct stevedore *stv, ...@@ -252,18 +251,11 @@ objallocwithnuke(struct worker *wrk, const struct stevedore *stv,
assert(size <= UINT_MAX); /* field limit in struct storage */ assert(size <= UINT_MAX); /* field limit in struct storage */
for (fail = 0; fail <= cache_param->nuke_limit; fail++) { AN(stv->alloc);
/* try to allocate from it */ do {
AN(stv->alloc);
st = STV_alloc(stv, size, flags); st = STV_alloc(stv, size, flags);
if (st != NULL) } while (st == NULL && EXP_NukeOne(wrk, stv->lru) == 1);
break;
/* 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); CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
return (st); return (st);
} }
......
...@@ -259,13 +259,15 @@ STV_NewObject(struct objcore *oc, struct worker *wrk, ...@@ -259,13 +259,15 @@ STV_NewObject(struct objcore *oc, struct worker *wrk,
const char *hint, unsigned wsl) const char *hint, unsigned wsl)
{ {
struct stevedore *stv, *stv0; struct stevedore *stv, *stv0;
int i, j; int j;
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
assert(wsl > 0); assert(wsl > 0);
wrk->strangelove = cache_param->nuke_limit;
stv = stv0 = stv_pick_stevedore(wrk->vsl, &hint); stv = stv0 = stv_pick_stevedore(wrk->vsl, &hint);
AN(stv);
AN(stv->allocobj); AN(stv->allocobj);
j = stv->allocobj(stv, oc, wsl); j = stv->allocobj(stv, oc, wsl);
if (j == 0 && hint == NULL) { if (j == 0 && hint == NULL) {
...@@ -275,15 +277,12 @@ STV_NewObject(struct objcore *oc, struct worker *wrk, ...@@ -275,15 +277,12 @@ STV_NewObject(struct objcore *oc, struct worker *wrk,
j = stv->allocobj(stv, oc, wsl); j = stv->allocobj(stv, oc, wsl);
} while (j == 0 && stv != stv0); } while (j == 0 && stv != stv0);
} }
if (j == 0) { while (j == 0) {
/* no luck; try to free some space and keep trying */ /* 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)
if (EXP_NukeOne(wrk, stv->lru) == -1) break;
break; j = stv->allocobj(stv, oc, wsl);
j = stv->allocobj(stv, oc, wsl);
}
} }
if (j == 0) if (j == 0)
return (0); return (0);
......
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment