[master] ab82163 Propagate BOS_FAILED to the objcore, and ignore OC_F_FAILED objects in HSH_Lookup()

Poul-Henning Kamp phk at varnish-cache.org
Tue Sep 3 13:57:28 CEST 2013


commit ab821632f695427357849fd63f36523600916e7a
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Sep 3 11:56:58 2013 +0000

    Propagate BOS_FAILED to the objcore, and ignore OC_F_FAILED objects
    in HSH_Lookup()

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 9b68f79..71bff9c 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -424,6 +424,7 @@ struct objcore {
 #define OC_F_PRIV		(1<<5)		/* Stevedore private flag */
 #define OC_F_LURK		(3<<6)		/* Ban-lurker-color */
 #define OC_F_PRIVATE		(1<<8)
+#define OC_F_FAILED		(1<<9)
 	unsigned		timer_idx;
 	VTAILQ_ENTRY(objcore)	list;
 	VTAILQ_ENTRY(objcore)	lru_list;
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index 1f8ec3d..d365158 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -118,7 +118,7 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
 	if (wrk->handling == VCL_RET_ABANDON) {
 		if (bo->req != NULL)
 			vbf_release_req(bo);
-		VBO_setstate(bo, BOS_FAILED);
+		(void)VFP_Error(bo, "Abandonned in vcl_backend_fetch");
 		return (F_STP_ABANDON);
 	}
 	assert (wrk->handling == VCL_RET_FETCH);
@@ -360,10 +360,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 	}
 	bo->stats = NULL;
 	if (obj == NULL) {
-		(void)HSH_Deref(&wrk->stats, bo->fetch_objcore, NULL);
-		bo->fetch_objcore = NULL;
+		(void)VFP_Error(bo, "Could not get storage");
 		VDI_CloseFd(&bo->vbc);
-		VBO_setstate(bo, BOS_FAILED);
 		return (F_STP_ABANDON);
 	}
 	CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
@@ -428,12 +426,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 
 	assert(bo->refcount >= 1);
 
-	if (bo->state == BOS_FAILED) {
-		/* handle early failures */
-		(void)HSH_Deref(&wrk->stats, NULL, &obj);
-		return (F_STP_ABANDON);
-	}
-	VBO_setstate(bo, BOS_FINISHED);
+	if (bo->state != BOS_FAILED)
+		VBO_setstate(bo, BOS_FINISHED);
 
 VSLb(bo->vsl, SLT_Debug, "YYY REF %d %d", bo->refcount, bo->fetch_obj->objcore->refcnt);
 	VBO_DerefBusyObj(wrk, &bo);	// XXX ?
@@ -450,6 +444,7 @@ vbf_stp_abandon(struct worker *wrk, struct busyobj *bo)
 	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
 
 	assert(bo->state == BOS_FAILED);
+	assert(bo->fetch_objcore->flags & OC_F_FAILED);
 	VBO_DerefBusyObj(wrk, &bo);	// XXX ?
 	return (F_STP_DONE);
 }
@@ -571,5 +566,8 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
 		return (NULL);
 	}
 	VBO_waitstate(bo, BOS_FETCHING);
+	if (!bo->do_stream)
+		VBO_waitstate(bo, BOS_FINISHED);
+	assert(bo->state != BOS_FAILED || (oc->flags & OC_F_FAILED));
 	return (bo);
 }
diff --git a/bin/varnishd/cache/cache_fetch_proc.c b/bin/varnishd/cache/cache_fetch_proc.c
index 37a2f4d..2871b73 100644
--- a/bin/varnishd/cache/cache_fetch_proc.c
+++ b/bin/varnishd/cache/cache_fetch_proc.c
@@ -62,6 +62,8 @@ VFP_Error2(struct busyobj *bo, const char *error, const char *more)
 			VSLb(bo->vsl, SLT_FetchError, "%s", error);
 		else
 			VSLb(bo->vsl, SLT_FetchError, "%s: %s", error, more);
+		if (bo->fetch_objcore != NULL)
+			HSH_Fail(bo->fetch_objcore);
 		VBO_setstate(bo, BOS_FAILED);
 	}
 	return (-1);
diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c
index 6fd51f6..ad63438 100644
--- a/bin/varnishd/cache/cache_hash.c
+++ b/bin/varnishd/cache/cache_hash.c
@@ -401,6 +401,9 @@ HSH_Lookup(struct req *req, struct objcore **ocp, struct objcore **bocp,
 		CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
 		assert(oc->objhead == oh);
 
+		if (oc->flags & OC_F_FAILED)
+			continue;
+
 		if (oc->flags & OC_F_BUSY || oc->busyobj != NULL) {
 			CHECK_OBJ_ORNULL(oc->busyobj, BUSYOBJ_MAGIC);
 			if (req->hash_ignore_busy)
@@ -624,6 +627,24 @@ HSH_Drop(struct worker *wrk, struct object **oo)
 }
 
 /*---------------------------------------------------------------------
+ * Fail an objcore
+ */
+
+void
+HSH_Fail(struct objcore *oc)
+{
+	struct objhead *oh;
+
+	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+	oh = oc->objhead;
+	CHECK_OBJ(oh, OBJHEAD_MAGIC);
+
+	Lck_Lock(&oh->mtx);
+	oc->flags |= OC_F_FAILED;
+	Lck_Unlock(&oh->mtx);
+}
+
+/*---------------------------------------------------------------------
  * Remove the busyobj from an objcore
  */
 
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index 442d7db..f8317b5 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -385,20 +385,18 @@ cnt_fetch(struct worker *wrk, struct req *req)
 	assert(bo->refcount > 0);
 	(void)HTTP1_DiscardReqBody(req);
 
-	/* bo->do_stream is not valid until after vcl_backend_response{} */
-	if (!bo->do_stream)
-		VBO_waitstate(bo, BOS_FINISHED);
-
-	if (bo->state == BOS_FAILED) {
+	if (req->objcore->flags & OC_F_FAILED) {
 		VBO_DerefBusyObj(wrk, &req->busyobj);
 		req->err_code = 503;
 		req->req_step = R_STP_ERROR;
+		req->objcore = NULL;
 		return (REQ_FSM_MORE);
 	}
 
 	assert (bo->state >= BOS_FETCHING);
 	req->err_code = bo->err_code;
 	req->obj = bo->fetch_obj;			// XXX: recnt ?
+	req->objcore = NULL;
 	if (bo->state == BOS_FINISHED)
 		VBO_DerefBusyObj(wrk, &req->busyobj);
 	assert(WRW_IsReleased(wrk));
@@ -609,7 +607,6 @@ cnt_miss(struct worker *wrk, struct req *req)
 
 	AN (req->objcore);
 	req->busyobj = VBF_Fetch(wrk, req, req->objcore, VBF_NORMAL);
-	req->objcore = NULL;
 	req->req_step = R_STP_FETCH;
 	return (REQ_FSM_MORE);
 }
@@ -634,7 +631,6 @@ XDOT err_pass [label="ERROR",shape=plaintext]
 static enum req_fsm_nxt
 cnt_pass(struct worker *wrk, struct req *req)
 {
-	struct objcore *oc;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
@@ -654,9 +650,9 @@ cnt_pass(struct worker *wrk, struct req *req)
 	assert (wrk->handling == VCL_RET_FETCH);
 	req->acct_req.pass++;
 
-	oc = HSH_Private(wrk);
-	AN(oc);
-	req->busyobj = VBF_Fetch(wrk, req, oc, VBF_PASS);
+	req->objcore = HSH_Private(wrk);
+	AN(req->objcore);
+	req->busyobj = VBF_Fetch(wrk, req, req->objcore, VBF_PASS);
 	req->req_step = R_STP_FETCH;
 	return (REQ_FSM_MORE);
 }
diff --git a/bin/varnishd/hash/hash_slinger.h b/bin/varnishd/hash/hash_slinger.h
index 79443c7..5d9e91d 100644
--- a/bin/varnishd/hash/hash_slinger.h
+++ b/bin/varnishd/hash/hash_slinger.h
@@ -108,6 +108,7 @@ struct objhead {
 #define hoh_head _u.n.u_n_hoh_head
 };
 
+void HSH_Fail(struct objcore *);
 void HSH_Unbusy(struct dstat *, struct objcore *);
 void HSH_Complete(struct objcore *oc);
 void HSH_DeleteObjHead(struct dstat *, struct objhead *oh);



More information about the varnish-commit mailing list