
phk at varnish-cache
Jul 8, 2013, 5:33 AM
Post #1 of 1
(44 views)
Permalink
|
|
[master] dd90a88 Minimal locking to prevent two backend fetches from trying to get at uncached req.body at the same time.
|
|
commit dd90a88b1c64b5880f2c4fcd83d3a8d3973d182c Author: Poul-Henning Kamp <phk [at] FreeBSD> Date: Mon Jul 8 12:33:26 2013 +0000 Minimal locking to prevent two backend fetches from trying to get at uncached req.body at the same time. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index b673eb1..eaaffb7 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -620,7 +620,7 @@ struct req { enum req_step req_step; VTAILQ_ENTRY(req) w_list; - enum req_body_state_e req_body_status; + volatile enum req_body_state_e req_body_status; struct storagehead body; struct { diff --git a/bin/varnishd/cache/cache_http1_fsm.c b/bin/varnishd/cache/cache_http1_fsm.c index d4a296a..9f150ea 100644 --- a/bin/varnishd/cache/cache_http1_fsm.c +++ b/bin/varnishd/cache/cache_http1_fsm.c @@ -490,9 +490,27 @@ HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv) return (0); case REQ_BODY_PRESENT: break; + case REQ_BODY_DONE: + case REQ_BODY_TAKEN: + VSLb(req->vsl, SLT_VCL_Error, + "Uncached req.body can only be consumed once."); + return (-1); default: WRONG("Wrong req_body_status in HTTP1_IterateReqBody()"); } + Lck_Lock(&req->sp->mtx); + if (req->req_body_status == REQ_BODY_PRESENT) { + req->req_body_status = REQ_BODY_TAKEN; + i = 0; + } else + i = -1; + Lck_Unlock(&req->sp->mtx); + if (i) { + VSLb(req->vsl, SLT_VCL_Error, + "Multiple attempts to access non-cached req.body"); + return (i); + } + do { l = http1_iter_req_body(req, buf, sizeof buf); if (l < 0) { @@ -531,11 +549,16 @@ HTTP1_DiscardReqBody(struct req *req) if (req->req_body_status == REQ_BODY_DONE) return(0); + if (req->req_body_status == REQ_BODY_TAKEN) + return(0); return(HTTP1_IterateReqBody(req, httpq_req_body_discard, NULL)); } /*---------------------------------------------------------------------- * Cache the req.body if it is smaller than the given size + * + * This function must be called before any backend fetches are kicked + * off to prevent parallelism. */ int diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index 3009e90..c63be80 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -494,6 +494,11 @@ VRT_CacheReqBody(const struct vrt_ctx *ctx, long long maxsize) CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); + if (ctx->method != VCL_MET_RECV) { + VSLb(ctx->vsl, SLT_VCL_Error, + "req.body can only be cached in vcl_recv{}"); + return (0); + } return (HTTP1_CacheReqBody(ctx->req, maxsize)); } _______________________________________________ varnish-commit mailing list varnish-commit [at] varnish-cache https://www.varnish-cache.org/lists/mailman/listinfo/varnish-commit
|