Skip to content
This repository was archived by the owner on Feb 16, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions bin/varnishd/cache/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ struct objcore {
uint16_t oa_present;

unsigned timer_idx; // XXX 4Gobj limit
unsigned waitinglist_gen;
Comment thread
nigoroll marked this conversation as resolved.
vtim_real last_lru;
VTAILQ_ENTRY(objcore) hsh_list;
VTAILQ_ENTRY(objcore) lru_list;
Expand Down Expand Up @@ -474,6 +475,7 @@ struct req {
stream_close_t doclose;
unsigned restarts;
unsigned max_restarts;
unsigned waitinglist_gen;

const struct req_step *req_step;
struct reqtop *top; /* esi_level == 0 request */
Expand All @@ -495,9 +497,6 @@ struct req {

struct objcore *body_oc;

/* The busy objhead we sleep on */
struct objhead *hash_objhead;

/* Built Vary string == workspace reservation */
uint8_t *vary_b;
uint8_t *vary_e;
Expand Down
2 changes: 1 addition & 1 deletion bin/varnishd/cache/cache_ban_lurker.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ ban_lurker_test_ban(struct worker *wrk, struct ban *bt,
if (i)
ObjSendEvent(wrk, oc, OEV_BANCHG);
}
(void)HSH_DerefObjCore(wrk, &oc, 0);
(void)HSH_DerefObjCore(wrk, &oc);
}
}

Expand Down
42 changes: 40 additions & 2 deletions bin/varnishd/cache/cache_busyobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ VBO_ReleaseBusyObj(struct worker *wrk, struct busyobj **pbo)
wrk->stats->ws_backend_overflow++;

if (bo->fetch_objcore != NULL) {
(void)HSH_DerefObjCore(wrk, &bo->fetch_objcore,
HSH_RUSH_POLICY);
(void)HSH_DerefObjCore(wrk, &bo->fetch_objcore);
}

VRT_Assign_Backend(&bo->director_req, NULL);
Expand All @@ -170,3 +169,42 @@ VBO_ReleaseBusyObj(struct worker *wrk, struct busyobj **pbo)

MPL_Free(vbopool, bo);
}

void
VBO_SetState(struct worker *wrk, struct busyobj *bo, enum boc_state_e next)
{
unsigned broadcast;

CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);

switch (next) {
case BOS_REQ_DONE:
AN(bo->req);
bo->req = NULL;
broadcast = bo->is_bgfetch;
break;
case BOS_STREAM:
AN(bo->do_stream);
AZ(bo->req);
broadcast = 1;
break;
case BOS_FINISHED:
case BOS_FAILED:
/* We can't assert that either state already released its
* request because a fetch may fail before reaching the
* BOS_REQ_DONE state. Failing can also mean executing
* vcl_backend_error and reaching BOS_FINISHED from there.
* One can legitemately return(retry) from there and proceed
* again with a usable req if a return(error) transition led
* to vcl_backend_error instead of a failed fetch attempt.
*/
bo->req = NULL;
broadcast = 1;
break;
default:
WRONG("unexpected BOC state");
}

ObjSetState(wrk, bo->fetch_objcore, next, broadcast);
}
6 changes: 3 additions & 3 deletions bin/varnishd/cache/cache_expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ EXP_Insert(struct worker *wrk, struct objcore *oc)
ObjSendEvent(wrk, oc, OEV_EXPIRE);
tmpoc = oc;
assert(oc->refcnt >= 2); /* Silence coverity */
(void)HSH_DerefObjCore(wrk, &oc, 0);
(void)HSH_DerefObjCore(wrk, &oc);
AZ(oc);
assert(tmpoc->refcnt >= 1); /* Silence coverity */
}
Expand Down Expand Up @@ -309,7 +309,7 @@ exp_inbox(struct exp_priv *ep, struct objcore *oc, unsigned flags, vtim_real now
VXID(ObjGetXID(ep->wrk, oc)), EXP_Ttl(NULL, oc) - now,
(intmax_t)oc->hits);
ObjSendEvent(ep->wrk, oc, OEV_EXPIRE);
(void)HSH_DerefObjCore(ep->wrk, &oc, 0);
(void)HSH_DerefObjCore(ep->wrk, &oc);
return;
}

Expand Down Expand Up @@ -387,7 +387,7 @@ exp_expire(struct exp_priv *ep, vtim_real now)
VXID(ObjGetXID(ep->wrk, oc)), EXP_Ttl(NULL, oc) - now,
(intmax_t)oc->hits);
ObjSendEvent(ep->wrk, oc, OEV_EXPIRE);
(void)HSH_DerefObjCore(ep->wrk, &oc, 0);
(void)HSH_DerefObjCore(ep->wrk, &oc);
}
return (0);
}
Expand Down
88 changes: 27 additions & 61 deletions bin/varnishd/cache/cache_fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,12 @@ vbf_stp_mkbereq(struct worker *wrk, struct busyobj *bo)
HTTP_Clone(bo->bereq, bo->bereq0);

if (bo->req->req_body_status->avail == 0) {
bo->req = NULL;
ObjSetState(bo->wrk, oc, BOS_REQ_DONE);
VBO_SetState(bo->wrk, bo, BOS_REQ_DONE);
} else if (bo->req->req_body_status == BS_CACHED) {
AN(bo->req->body_oc);
bo->bereq_body = bo->req->body_oc;
HSH_Ref(bo->bereq_body);
bo->req = NULL;
ObjSetState(bo->wrk, oc, BOS_REQ_DONE);
VBO_SetState(bo->wrk, bo, BOS_REQ_DONE);
}
return (F_STP_STARTFETCH);
}
Expand Down Expand Up @@ -544,10 +542,8 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)

VSLb_ts_busyobj(bo, "Process", W_TIM_real(wrk));
assert(oc->boc->state <= BOS_REQ_DONE);
if (oc->boc->state != BOS_REQ_DONE) {
bo->req = NULL;
ObjSetState(wrk, oc, BOS_REQ_DONE);
}
if (oc->boc->state != BOS_REQ_DONE)
VBO_SetState(wrk, bo, BOS_REQ_DONE);

if (bo->do_esi)
bo->do_stream = 0;
Expand Down Expand Up @@ -712,11 +708,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)

assert(oc->boc->state == BOS_REQ_DONE);

if (bo->do_stream) {
ObjSetState(wrk, oc, BOS_PREP_STREAM);
HSH_Unbusy(wrk, oc);
ObjSetState(wrk, oc, BOS_STREAM);
}
if (bo->do_stream)
Comment thread
dridi marked this conversation as resolved.
VBO_SetState(wrk, bo, BOS_STREAM);

VSLb(bo->vsl, SLT_Fetch_Body, "%u %s %s",
bo->htc->body_status->nbr, bo->htc->body_status->name,
Expand Down Expand Up @@ -751,13 +744,10 @@ vbf_stp_fetchend(struct worker *wrk, struct busyobj *bo)

if (bo->do_stream)
assert(oc->boc->state == BOS_STREAM);
else {
else
assert(oc->boc->state == BOS_REQ_DONE);
ObjSetState(wrk, oc, BOS_PREP_STREAM);
HSH_Unbusy(wrk, oc);
}

ObjSetState(wrk, oc, BOS_FINISHED);
VBO_SetState(wrk, bo, BOS_FINISHED);
VSLb_ts_busyobj(bo, "BerespBody", W_TIM_real(wrk));
if (bo->stale_oc != NULL) {
VSL(SLT_ExpKill, NO_VXID, "VBF_Superseded x=%ju n=%ju",
Expand Down Expand Up @@ -884,11 +874,8 @@ vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo)
ObjSetFlag(bo->wrk, oc, OF_IMSCAND, 0);
AZ(ObjCopyAttr(bo->wrk, oc, stale_oc, OA_GZIPBITS));

if (bo->do_stream) {
ObjSetState(wrk, oc, BOS_PREP_STREAM);
HSH_Unbusy(wrk, oc);
ObjSetState(wrk, oc, BOS_STREAM);
}
if (bo->do_stream)
VBO_SetState(wrk, bo, BOS_STREAM);

INIT_OBJ(vop, VBF_OBITER_PRIV_MAGIC);
vop->bo = bo;
Expand All @@ -909,9 +896,7 @@ vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo)
*
* replaces a stale object unless
* - abandoning the bereq or
* - leaving vcl_backend_error with return (deliver) and beresp.ttl == 0s or
* - there is a waitinglist on this object because in this case the default ttl
* would be 1s, so we might be looking at the same case as the previous
* - leaving vcl_backend_error with return (deliver)
*
* We do want the stale replacement to avoid an object pileup with short ttl and
* long grace/keep, yet there could exist cases where a cache object is
Expand All @@ -934,7 +919,8 @@ vbf_stp_error(struct worker *wrk, struct busyobj *bo)
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
oc = bo->fetch_objcore;
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
AN(oc->flags & OC_F_BUSY);
CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
assert(oc->boc->state < BOS_STREAM);
assert(bo->director_state == DIR_S_NULL);

if (wrk->vpi->handling != VCL_RET_ERROR)
Expand Down Expand Up @@ -968,23 +954,9 @@ vbf_stp_error(struct worker *wrk, struct busyobj *bo)

stale = bo->stale_oc;
oc->t_origin = now;
if (!VTAILQ_EMPTY(&oc->objhead->waitinglist)) {
/*
* If there is a waitinglist, it means that there is no
* grace-able object, so cache the error return for a
* short time, so the waiting list can drain, rather than
* each objcore on the waiting list sequentially attempt
* to fetch from the backend.
*/
oc->ttl = 1;
oc->grace = 5;
oc->keep = 5;
stale = NULL;
} else {
oc->ttl = 0;
oc->grace = 0;
oc->keep = 0;
}
oc->ttl = 0;
oc->grace = 0;
oc->keep = 0;

synth_body = VSB_new_auto();
AN(synth_body);
Expand Down Expand Up @@ -1037,11 +1009,9 @@ vbf_stp_error(struct worker *wrk, struct busyobj *bo)
assert(o == VSB_len(synth_body));
AZ(ObjSetU64(wrk, oc, OA_LEN, o));
VSB_destroy(&synth_body);
ObjSetState(wrk, oc, BOS_PREP_STREAM);
HSH_Unbusy(wrk, oc);
if (stale != NULL && oc->ttl > 0)
HSH_Kill(stale);
ObjSetState(wrk, oc, BOS_FINISHED);
VBO_SetState(wrk, bo, BOS_FINISHED);
return (F_STP_DONE);
}

Expand All @@ -1059,10 +1029,8 @@ vbf_stp_fail(struct worker *wrk, struct busyobj *bo)
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);

assert(oc->boc->state < BOS_FINISHED);
HSH_Fail(oc);
if (!(oc->flags & OC_F_BUSY))
HSH_Kill(oc);
ObjSetState(wrk, oc, BOS_FAILED);
VBO_SetState(wrk, bo, BOS_FAILED);
HSH_Kill(oc);
return (F_STP_DONE);
}

Expand Down Expand Up @@ -1134,7 +1102,7 @@ vbf_fetch_thread(struct worker *wrk, void *priv)
http_Teardown(bo->beresp);
// cannot make assumptions about the number of references here #3434
if (bo->bereq_body != NULL)
(void) HSH_DerefObjCore(bo->wrk, &bo->bereq_body, 0);
(void)HSH_DerefObjCore(bo->wrk, &bo->bereq_body);

if (oc->boc->state == BOS_FINISHED) {
AZ(oc->flags & OC_F_FAILED);
Expand All @@ -1144,7 +1112,7 @@ vbf_fetch_thread(struct worker *wrk, void *priv)
// AZ(oc->boc); // XXX

if (bo->stale_oc != NULL)
(void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
(void)HSH_DerefObjCore(wrk, &bo->stale_oc);

wrk->vsl = NULL;
HSH_DerefBoc(wrk, oc);
Expand All @@ -1168,7 +1136,6 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
AN(oc->flags & OC_F_BUSY);
CHECK_OBJ_ORNULL(oldoc, OBJCORE_MAGIC);

bo = VBO_GetBusyObj(wrk, req);
Expand All @@ -1177,6 +1144,7 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,

boc = HSH_RefBoc(oc);
CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
assert(boc->state < BOS_STREAM);
boc->transit_buffer = cache_param->transit_buffer;

switch (mode) {
Expand Down Expand Up @@ -1236,7 +1204,7 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
"No thread available for bgfetch");
(void)vbf_stp_fail(req->wrk, bo);
if (bo->stale_oc != NULL)
(void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
(void)HSH_DerefObjCore(wrk, &bo->stale_oc);
HSH_DerefBoc(wrk, oc);
SES_Rel(bo->sp);
THR_SetBusyobj(NULL);
Expand All @@ -1249,17 +1217,15 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
(void)VRB_Ignore(req);
} else {
ObjWaitState(oc, BOS_STREAM);
if (oc->boc->state == BOS_FAILED) {
AN((oc->flags & OC_F_FAILED));
} else {
AZ(oc->flags & OC_F_BUSY);
}
AZ(oc->flags & OC_F_BUSY);
Comment thread
nigoroll marked this conversation as resolved.
if (oc->boc->state == BOS_FAILED)
AN(oc->flags & OC_F_FAILED);
}
}
AZ(bo);
VSLb_ts_req(req, "Fetch", W_TIM_real(wrk));
assert(oc->boc == boc);
HSH_DerefBoc(wrk, oc);
if (mode == VBF_BACKGROUND)
(void)HSH_DerefObjCore(wrk, &oc, HSH_RUSH_POLICY);
(void)HSH_DerefObjCore(wrk, &oc);
}
Loading