---
 bin/varnishd/cache/cache.h                     | 17 +++++----
 bin/varnishd/cache/cache_ban.c                 |  4 +--
 bin/varnishd/cache/cache_expire.c              | 49 +++++++++++---------------
 bin/varnishd/cache/cache_fetch.c               | 34 +++++++++---------
 bin/varnishd/cache/cache_hash.c                | 28 +++++++--------
 bin/varnishd/cache/cache_req_fsm.c             |  2 +-
 bin/varnishd/cache/cache_rfc2616.c             |  2 +-
 bin/varnishd/cache/cache_vrt_var.c             | 22 ++++++------
 bin/varnishd/storage/stevedore.c               |  7 ++--
 bin/varnishd/storage/storage_persistent.c      |  9 +++--
 bin/varnishd/storage/storage_persistent_silo.c | 36 +++++++++++--------
 include/persistent.h                           |  5 +--
 12 files changed, 105 insertions(+), 110 deletions(-)

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index b0740c1..c15473d 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -404,7 +404,7 @@ struct storage {
 typedef struct object *getobj_f(struct dstat *ds, struct objcore *oc);
 typedef unsigned getxid_f(struct dstat *ds, struct objcore *oc);
 typedef void updatemeta_f(struct objcore *oc);
-typedef void freeobj_f(struct objcore *oc);
+typedef void freeobj_f(struct dstat *ds, struct objcore *oc);
 typedef struct lru *getlru_f(const struct objcore *oc);
 
 struct objcore_methods {
@@ -446,6 +446,8 @@ struct objcore {
        double                  last_lru;
        VTAILQ_ENTRY(objcore)   ban_list;
        struct ban              *ban;
+
+       struct exp              exp;
 };
 
 static inline unsigned
@@ -480,13 +482,13 @@ oc_updatemeta(struct objcore *oc)
 }
 
 static inline void
-oc_freeobj(struct objcore *oc)
+oc_freeobj(struct dstat *ds, struct objcore *oc)
 {
 
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
        AN(oc->methods);
        AN(oc->methods->freeobj);
-       oc->methods->freeobj(oc);
+       oc->methods->freeobj(ds, oc);
 }
 
 static inline struct lru *
@@ -553,7 +555,6 @@ struct busyobj {
        struct objcore          *fetch_objcore;
        struct object           *fetch_obj;
 
-       struct exp              exp;
        struct http_conn        htc;
 
        struct pool_task        fetch_task;
@@ -612,8 +613,6 @@ struct object {
 
        ssize_t                 len;
 
-       struct exp              exp;
-
        /* VCL only variables */
        double                  last_modified;
 
@@ -917,11 +916,11 @@ extern pthread_t cli_thread;
 /* cache_expiry.c */
 void EXP_Clr(struct exp *e);
 
-double EXP_Ttl(const struct req *, const struct object*);
+double EXP_Ttl(const struct req *, const struct objcore *);
 void EXP_Insert(struct objcore *oc);
-void EXP_Inject(struct objcore *oc, struct lru *lru, double when);
+void EXP_Inject(struct objcore *oc, struct lru *lru, const struct exp *exp);
 void EXP_Init(void);
-void EXP_Rearm(struct object *o, double now, double ttl, double grace,
+void EXP_Rearm(struct objcore *oc, double now, double ttl, double grace,
     double keep);
 void EXP_Touch(struct objcore *oc, double now);
 int EXP_NukeOne(struct busyobj *, struct lru *lru);
diff --git a/bin/varnishd/cache/cache_ban.c b/bin/varnishd/cache/cache_ban.c
index 99f2914..b60ed9e 100644
--- a/bin/varnishd/cache/cache_ban.c
+++ b/bin/varnishd/cache/cache_ban.c
@@ -964,7 +964,7 @@ ban_check_object(struct object *o, struct vsl_log *vsl,
                oc->ban = NULL;
                VSLb(vsl, SLT_ExpBan, "%u banned lookup", o->vxid);
                VSC_C_main->bans_obj_killed++;
-               EXP_Rearm(o, o->exp.t_origin, 0, 0, 0); // XXX fake now
+               EXP_Rearm(oc, oc->exp.t_origin, 0, 0, 0);       // XXX fake now
                return (1);
        }
 }
@@ -1105,7 +1105,7 @@ ban_lurker_test_ban(struct worker *wrk, struct vsl_log 
*vsl, struct ban *bt,
                }
                if (i) {
                        VSLb(vsl, SLT_ExpBan, "%u banned by lurker", o->vxid);
-                       EXP_Rearm(o, o->exp.t_origin, 0, 0, 0); // XXX fake now
+                       EXP_Rearm(oc, oc->exp.t_origin, 0, 0, 0);// XXX fake now
                        VSC_C_main->bans_lurker_obj_killed++;
                }
                (void)HSH_DerefObjCore(&wrk->stats, &oc);
diff --git a/bin/varnishd/cache/cache_expire.c 
b/bin/varnishd/cache/cache_expire.c
index b5ecfbe..864d679 100644
--- a/bin/varnishd/cache/cache_expire.c
+++ b/bin/varnishd/cache/cache_expire.c
@@ -76,14 +76,14 @@ EXP_Clr(struct exp *e)
  */
 
 double
-EXP_Ttl(const struct req *req, const struct object *o)
+EXP_Ttl(const struct req *req, const struct objcore *oc)
 {
        double r;
 
-       r = o->exp.ttl;
+       r = oc->exp.ttl;
        if (req != NULL && req->d_ttl > 0. && req->d_ttl < r)
                r = req->d_ttl;
-       return (o->exp.t_origin + r);
+       return (oc->exp.t_origin + r);
 }
 
 /*--------------------------------------------------------------------
@@ -91,13 +91,11 @@ EXP_Ttl(const struct req *req, const struct object *o)
  */
 
 static double
-exp_when(const struct object *o)
+exp_when(const struct exp *exp)
 {
        double when;
 
-       CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-
-       when = o->exp.t_origin + o->exp.ttl + o->exp.grace + o->exp.keep;
+       when = exp->t_origin + exp->ttl + exp->grace + exp->keep;
        AZ(isnan(when));
        return (when);
 }
@@ -130,7 +128,7 @@ exp_mail_it(struct objcore *oc)
  */
 
 void
-EXP_Inject(struct objcore *oc, struct lru *lru, double when)
+EXP_Inject(struct objcore *oc, struct lru *lru, const struct exp *exp)
 {
 
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
@@ -146,10 +144,12 @@ EXP_Inject(struct objcore *oc, struct lru *lru, double 
when)
        Lck_Lock(&lru->mtx);
        lru->n_objcore++;
        oc->exp_flags |= OC_EF_OFFLRU | OC_EF_INSERT | OC_EF_EXP;
-       if (when < 0)
+       if (exp == NULL)
                oc->exp_flags |= OC_EF_MOVE;
-       else
-               oc->timer_when = when;
+       else {
+               oc->exp = *exp;
+               oc->timer_when = exp_when(exp);
+       }
        Lck_Unlock(&lru->mtx);
 
        exp_mail_it(oc);
@@ -168,7 +168,7 @@ EXP_Insert(struct objcore *oc)
 
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
        HSH_Ref(oc);
-       EXP_Inject(oc, NULL, -1);
+       EXP_Inject(oc, NULL, NULL);
 }
 
 /*--------------------------------------------------------------------
@@ -223,32 +223,29 @@ EXP_Touch(struct objcore *oc, double now)
  */
 
 void
-EXP_Rearm(struct object *o, double now, double ttl, double grace, double keep)
+EXP_Rearm(struct objcore *oc, double now, double ttl, double grace, double 
keep)
 {
-       struct objcore *oc;
        struct lru *lru;
        double when;
 
-       CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-       oc = o->objcore;
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
        assert(oc->refcnt > 0);
 
        AN(oc->exp_flags & OC_EF_EXP);
 
        if (!isnan(ttl))
-               o->exp.ttl = now + ttl - o->exp.t_origin;
+               oc->exp.ttl = now + ttl - oc->exp.t_origin;
        if (!isnan(grace))
-               o->exp.grace = grace;
+               oc->exp.grace = grace;
        if (!isnan(keep))
-               o->exp.keep = keep;
+               oc->exp.keep = keep;
 
-       when = exp_when(o);
+       when = exp_when(&oc->exp);
 
        VSL(SLT_ExpKill, 0, "EXP_Rearm p=%p E=%.9f e=%.9f f=0x%x", oc,
            oc->timer_when, when, oc->flags);
 
-       if (when > o->exp.t_origin && when > oc->timer_when)
+       if (when > oc->exp.t_origin && when > oc->timer_when)
                return;
 
        lru = oc_getlru(oc);
@@ -419,7 +416,6 @@ exp_inbox(struct exp_priv *ep, struct objcore *oc, double 
now)
 {
        unsigned flags;
        struct lru *lru;
-       struct object *o;
 
        CHECK_OBJ_NOTNULL(ep, EXP_PRIV_MAGIC);
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
@@ -457,9 +453,7 @@ exp_inbox(struct exp_priv *ep, struct objcore *oc, double 
now)
        }
 
        if (flags & OC_EF_MOVE) {
-               o = oc_getobj(&ep->wrk->stats, oc);
-               CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-               oc->timer_when = exp_when(o);
+               oc->timer_when = exp_when(&oc->exp);
                oc_updatemeta(oc);
        }
 
@@ -494,7 +488,6 @@ exp_expire(struct exp_priv *ep, double now)
 {
        struct lru *lru;
        struct objcore *oc;
-       struct object *o;
 
        CHECK_OBJ_NOTNULL(ep, EXP_PRIV_MAGIC);
 
@@ -532,11 +525,9 @@ exp_expire(struct exp_priv *ep, double now)
        assert(oc->timer_idx == BINHEAP_NOIDX);
 
        CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC);
-       o = oc_getobj(&ep->wrk->stats, oc);
-       CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
        VSLb(&ep->vsl, SLT_ExpKill, "EXP_Expired x=%u t=%.0f",
            oc_getxid(&ep->wrk->stats, oc) & VSL_IDENTMASK,
-           EXP_Ttl(NULL, o) - now);
+           EXP_Ttl(NULL, oc) - now);
        (void)HSH_DerefObjCore(&ep->wrk->stats, &oc);
        return (0);
 }
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index f8e2848..0176309 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -55,7 +55,8 @@ vbf_allocobj(struct busyobj *bo, unsigned l, uint16_t nhttp)
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
 
-       lifetime = bo->exp.ttl + bo->exp.grace + bo->exp.keep;
+       lifetime = bo->fetch_objcore->exp.ttl + bo->fetch_objcore->exp.grace +
+           bo->fetch_objcore->exp.keep;
 
        if (bo->uncacheable || lifetime < cache_param->shortlived)
                storage_hint = TRANSIENT_STORAGE;
@@ -77,10 +78,10 @@ vbf_allocobj(struct busyobj *bo, unsigned l, uint16_t nhttp)
         * on Transient storage.
         */
 
-       if (bo->exp.ttl > cache_param->shortlived)
-               bo->exp.ttl = cache_param->shortlived;
-       bo->exp.grace = 0.0;
-       bo->exp.keep = 0.0;
+       if (bo->fetch_objcore->exp.ttl > cache_param->shortlived)
+               bo->fetch_objcore->exp.ttl = cache_param->shortlived;
+       bo->fetch_objcore->exp.grace = 0.0;
+       bo->fetch_objcore->exp.keep = 0.0;
        obj = STV_NewObject(bo, TRANSIENT_STORAGE, l, nhttp);
        return (obj);
 }
@@ -162,7 +163,7 @@ vbf_beresp2obj(struct busyobj *bo)
        if (http_GetHdr(hp, H_Last_Modified, &b))
                obj->last_modified = VTIM_parse(b);
        else
-               obj->last_modified = floor(bo->exp.t_origin);
+               obj->last_modified = floor(bo->fetch_objcore->exp.t_origin);
 
        return (0);
 }
@@ -346,12 +347,12 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
        /*
         * What does RFC2616 think about TTL ?
         */
-       EXP_Clr(&bo->exp);
+       EXP_Clr(&bo->fetch_objcore->exp);
        RFC2616_Ttl(bo, now);
 
        /* private objects have negative TTL */
        if (bo->fetch_objcore->flags & OC_F_PRIVATE)
-               bo->exp.ttl = -1.;
+               bo->fetch_objcore->exp.ttl = -1.;
 
        AZ(bo->do_esi);
 
@@ -531,9 +532,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
        if (bo->failed && !bo->do_stream) {
                assert(bo->state < BOS_STREAM);
                if (bo->fetch_obj != NULL) {
-                       oc_freeobj(bo->fetch_objcore);
+                       oc_freeobj(bo->stats, bo->fetch_objcore);
                        bo->fetch_obj = NULL;
-                       bo->stats->n_object--;
                }
                return (F_STP_ERROR);
        }
@@ -646,7 +646,8 @@ vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo)
 
        assert(al == bo->ims_obj->len);
        assert(obj->len == al);
-       EXP_Rearm(bo->ims_obj, bo->ims_obj->exp.t_origin, 0, 0, 0);
+       EXP_Rearm(bo->ims_obj->objcore, bo->ims_obj->objcore->exp.t_origin,
+           0, 0, 0);
 
        /* Recycle the backend connection before setting BOS_FINISHED to
           give predictable backend reuse behavior for varnishtest */
@@ -692,10 +693,10 @@ vbf_stp_error(struct worker *wrk, struct busyobj *bo)
        http_PrintfHeader(bo->beresp, "Date: %s", time_str);
        http_SetHeader(bo->beresp, "Server: Varnish");
 
-       bo->exp.t_origin = bo->t_prev;
-       bo->exp.ttl = 0;
-       bo->exp.grace = 0;
-       bo->exp.keep = 0;
+       bo->fetch_objcore->exp.t_origin = bo->t_prev;
+       bo->fetch_objcore->exp.ttl = 0;
+       bo->fetch_objcore->exp.grace = 0;
+       bo->fetch_objcore->exp.keep = 0;
 
        VCL_backend_error_method(bo->vcl, wrk, NULL, bo, bo->bereq->ws);
 
@@ -751,7 +752,8 @@ vbf_stp_fail(struct worker *wrk, struct busyobj *bo)
        if (bo->fetch_objcore->exp_flags & OC_EF_EXP) {
                /* Already unbusied - expire it */
                AN(bo->fetch_obj);
-               EXP_Rearm(bo->fetch_obj, bo->fetch_obj->exp.t_origin, 0, 0, 0);
+               EXP_Rearm(bo->fetch_obj->objcore,
+                   bo->fetch_obj->objcore->exp.t_origin, 0, 0, 0);
        }
        wrk->stats.fetch_failed++;
        VBO_setstate(bo, BOS_FAILED);
diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c
index f4bbae0..3234571 100644
--- a/bin/varnishd/cache/cache_hash.c
+++ b/bin/varnishd/cache/cache_hash.c
@@ -420,17 +420,18 @@ HSH_Lookup(struct req *req, struct objcore **ocp, struct 
objcore **bocp,
                        continue;
                }
 
+               if (oc->exp.ttl <= 0.)
+                       continue;
+
                o = oc_getobj(&wrk->stats, oc);
                CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
 
-               if (o->exp.ttl <= 0.)
-                       continue;
                if (BAN_CheckObject(o, req))
                        continue;
                if (o->vary != NULL && !VRY_Match(req, o->vary))
                        continue;
 
-               if (EXP_Ttl(req, o) >= req->t_req) {
+               if (EXP_Ttl(req, oc) >= req->t_req) {
                        /* If still valid, use it */
                        assert(oh->refcnt > 1);
                        assert(oc->objhead == oh);
@@ -442,12 +443,12 @@ HSH_Lookup(struct req *req, struct objcore **ocp, struct 
objcore **bocp,
                        *ocp = oc;
                        return (HSH_HIT);
                }
-               if (o->exp.t_origin > exp_t_origin &&
+               if (oc->exp.t_origin > exp_t_origin &&
                    !(oc->flags & OC_F_PASS)) {
                        /* record the newest object */
                        exp_oc = oc;
                        exp_o = o;
-                       exp_t_origin = o->exp.t_origin;
+                       exp_t_origin = oc->exp.t_origin;
                }
        }
 
@@ -559,7 +560,6 @@ HSH_Purge(struct worker *wrk, struct objhead *oh, double 
ttl, double grace)
 {
        struct objcore *oc, **ocp;
        unsigned spc, nobj, n;
-       struct object *o;
        double now;
 
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
@@ -594,12 +594,10 @@ HSH_Purge(struct worker *wrk, struct objhead *oh, double 
ttl, double grace)
        for (n = 0; n < nobj; n++) {
                oc = ocp[n];
                CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-               o = oc_getobj(&wrk->stats, oc);
-               if (o == NULL)
+               if (!(oc->exp_flags & OC_EF_EXP))
                        continue;
-               CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-               EXP_Rearm(o, now, ttl, grace, NAN);     // XXX: Keep ?
-               (void)HSH_DerefObj(&wrk->stats, &o);
+               EXP_Rearm(oc, now, ttl, grace, NAN);    // XXX: Keep ?
+               (void)HSH_DerefObjCore(&wrk->stats, &oc);
        }
        WS_Release(wrk->aws, 0);
 }
@@ -616,7 +614,7 @@ HSH_Drop(struct worker *wrk, struct object **oo)
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
        AN(oo);
        CHECK_OBJ_NOTNULL(*oo, OBJECT_MAGIC);
-       (*oo)->exp.ttl = -1.;
+       (*oo)->objcore->exp.ttl = -1.;
        AZ(HSH_DerefObj(&wrk->stats, oo));
 }
 
@@ -802,10 +800,8 @@ HSH_DerefObjCore(struct dstat *ds, struct objcore **ocp)
        BAN_DestroyObj(oc);
        AZ(oc->ban);
 
-       if (oc->methods != NULL) {
-               oc_freeobj(oc);
-               ds->n_object--;
-       }
+       if (oc->methods != NULL)
+               oc_freeobj(ds, oc);
        FREE_OBJ(oc);
 
        ds->n_objectcore--;
diff --git a/bin/varnishd/cache/cache_req_fsm.c 
b/bin/varnishd/cache/cache_req_fsm.c
index d465ba4..2201049 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -122,7 +122,7 @@ cnt_deliver(struct worker *wrk, struct req *req)
           age. Truncate to zero in that case).
        */
        http_PrintfHeader(req->resp, "Age: %.0f",
-           fmax(0., req->t_prev - req->obj->exp.t_origin));
+           fmax(0., req->t_prev - req->obj->objcore->exp.t_origin));
 
        http_SetHeader(req->resp, "Via: 1.1 varnish (v4)");
 
diff --git a/bin/varnishd/cache/cache_rfc2616.c 
b/bin/varnishd/cache/cache_rfc2616.c
index bb0a85e..8ada968 100644
--- a/bin/varnishd/cache/cache_rfc2616.c
+++ b/bin/varnishd/cache/cache_rfc2616.c
@@ -72,7 +72,7 @@ RFC2616_Ttl(struct busyobj *bo, double now)
        struct exp *expp;
 
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
-       expp = &bo->exp;
+       expp = &bo->fetch_objcore->exp;
 
        hp = bo->beresp;
 
diff --git a/bin/varnishd/cache/cache_vrt_var.c 
b/bin/varnishd/cache/cache_vrt_var.c
index b68031c..ca84bb0 100644
--- a/bin/varnishd/cache/cache_vrt_var.c
+++ b/bin/varnishd/cache/cache_vrt_var.c
@@ -461,17 +461,17 @@ VRT_r_##which##_##fld(const struct vrt_ctx *ctx)          
\
        return(0.0);                                            \
 }
 
-VRT_DO_EXP_R(obj, ctx->req->obj->exp, ttl,
-   (ctx->req->t_req - ctx->req->obj->exp.t_origin))
-VRT_DO_EXP_R(obj, ctx->req->obj->exp, grace, 0)
-VRT_DO_EXP_R(obj, ctx->req->obj->exp, keep, 0)
-
-VRT_DO_EXP_L(beresp, ctx->bo->exp, ttl)
-VRT_DO_EXP_R(beresp, ctx->bo->exp, ttl, 0)
-VRT_DO_EXP_L(beresp, ctx->bo->exp, grace)
-VRT_DO_EXP_R(beresp, ctx->bo->exp, grace, 0)
-VRT_DO_EXP_L(beresp, ctx->bo->exp, keep)
-VRT_DO_EXP_R(beresp, ctx->bo->exp, keep, 0)
+VRT_DO_EXP_R(obj, ctx->req->obj->objcore->exp, ttl,
+   (ctx->req->t_req - ctx->req->obj->objcore->exp.t_origin))
+VRT_DO_EXP_R(obj, ctx->req->obj->objcore->exp, grace, 0)
+VRT_DO_EXP_R(obj, ctx->req->obj->objcore->exp, keep, 0)
+
+VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore->exp, ttl)
+VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore->exp, ttl, 0)
+VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore->exp, grace)
+VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore->exp, grace, 0)
+VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore->exp, keep)
+VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore->exp, keep, 0)
 
 /*--------------------------------------------------------------------
  * [be]req.xid
diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c
index 5e54ed6..6fc3ce2 100644
--- a/bin/varnishd/storage/stevedore.c
+++ b/bin/varnishd/storage/stevedore.c
@@ -70,7 +70,7 @@ default_oc_getobj(struct dstat *ds, struct objcore *oc)
 }
 
 static void
-default_oc_freeobj(struct objcore *oc)
+default_oc_freeobj(struct dstat *ds, struct objcore *oc)
 {
        struct object *o;
 
@@ -81,6 +81,8 @@ default_oc_freeobj(struct objcore *oc)
 
        STV_Freestore(o);
        STV_free(o->objstore);
+
+       ds->n_object--;
 }
 
 static struct lru *
@@ -283,9 +285,7 @@ STV_MkObject(struct stevedore *stv, struct busyobj *bo,
 
        HTTP_Setup(o->http, bo->ws_o, bo->vsl, SLT_ObjMethod);
        o->http->magic = HTTP_MAGIC;
-       o->exp = bo->exp;
        VTAILQ_INIT(&o->store);
-       bo->stats->n_object++;
 
        o->objcore = bo->fetch_objcore;
 
@@ -321,6 +321,7 @@ stv_default_allocobj(struct stevedore *stv, struct busyobj 
*bo,
        o = STV_MkObject(stv, bo, st->ptr, ltot, soc);
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
        o->objstore = st;
+       bo->stats->n_object++;
        return (o);
 }
 
diff --git a/bin/varnishd/storage/storage_persistent.c 
b/bin/varnishd/storage/storage_persistent.c
index d7506f0..a931f81 100644
--- a/bin/varnishd/storage/storage_persistent.c
+++ b/bin/varnishd/storage/storage_persistent.c
@@ -474,7 +474,7 @@ smp_allocx(struct stevedore *st, size_t min_size, size_t 
max_size,
                        sc->next_top -= sizeof(**so);
                        *so = (void*)(sc->base + sc->next_top);
                        /* Render this smp_object mostly harmless */
-                       (*so)->ttl = 0.;
+                       EXP_Clr(&(*so)->exp);
                        (*so)->ban = 0.;
                        (*so)->ptr = 0;
                        sg->objs = *so;
@@ -521,7 +521,9 @@ smp_allocobj(struct stevedore *stv, struct busyobj *bo,
        if (bo->fetch_objcore == NULL)
                return (NULL);          /* from cnt_error */
        CAST_OBJ_NOTNULL(sc, stv->priv, SMP_SC_MAGIC);
-       AN((bo->exp.ttl + bo->exp.grace + bo->exp.keep) > 0.);
+       assert((bo->fetch_objcore->exp.ttl +
+               bo->fetch_objcore->exp.grace +
+               bo->fetch_objcore->exp.keep) > 0.);
 
        ltot = IRNUP(sc, ltot);
 
@@ -535,6 +537,7 @@ smp_allocobj(struct stevedore *stv, struct busyobj *bo,
        o = STV_MkObject(stv, bo, st->ptr, ltot, soc);
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
        o->objstore = st;
+       bo->stats->n_object++;
 
        oc = o->objcore;
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
@@ -546,7 +549,7 @@ smp_allocobj(struct stevedore *stv, struct busyobj *bo,
        /* We have to do this somewhere, might as well be here... */
        assert(sizeof so->hash == DIGEST_LEN);
        memcpy(so->hash, oc->objhead->digest, DIGEST_LEN);
-       so->ttl = oc->timer_when;
+       so->exp = oc->exp;
        so->ptr = (uint8_t*)o - sc->base;
        so->ban = BAN_Time(oc->ban);
 
diff --git a/bin/varnishd/storage/storage_persistent_silo.c 
b/bin/varnishd/storage/storage_persistent_silo.c
index f27ccd9..f561159 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -127,6 +127,7 @@ smp_load_seg(struct worker *wrk, const struct smp_sc *sc,
        uint32_t no;
        double t_now = VTIM_real();
        struct smp_signctx ctx[1];
+       const struct exp *exp;
 
        ASSERT_SILO_THREAD(sc);
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
@@ -149,7 +150,9 @@ smp_load_seg(struct worker *wrk, const struct smp_sc *sc,
        /* Clear the bogus "hold" count */
        sg->nobj = 0;
        for (;no > 0; so++,no--) {
-               if (so->ttl == 0 || so->ttl < t_now)
+               exp = &so->exp;
+               if (exp->ttl < 0. ||
+                   (exp->t_origin + exp->ttl + exp->grace + exp->keep < t_now))
                        continue;
                ALLOC_OBJ(oc, OBJCORE_MAGIC);
                AN(oc);
@@ -158,7 +161,7 @@ smp_load_seg(struct worker *wrk, const struct smp_sc *sc,
                smp_init_oc(oc, sg, no);
                oc->ban = BAN_RefBan(oc, so->ban, sc->tailban);
                HSH_Insert(wrk, so->hash, oc);
-               EXP_Inject(oc, sg->lru, so->ttl);
+               EXP_Inject(oc, sg->lru, &so->exp);
                sg->nobj++;
        }
        WRK_SumStat(wrk);
@@ -415,7 +418,7 @@ smp_oc_getobj(struct dstat *ds, struct objcore *oc)
        struct smp_object *so;
        struct storage *st;
        uint64_t l;
-       int bad;
+       int bad = 0;
 
        /* Some calls are direct, but they should match anyway */
        assert(oc->methods->getobj == smp_oc_getobj);
@@ -451,7 +454,6 @@ smp_oc_getobj(struct dstat *ds, struct objcore *oc)
                /* We trust caller to have a refcnt for us */
                o->objcore = oc;
 
-               bad = 0;
                l = 0;
                VTAILQ_FOREACH(st, &o->store, list) {
                        bad |= smp_loaded_st(sg->sc, sg, st);
@@ -462,10 +464,8 @@ smp_oc_getobj(struct dstat *ds, struct objcore *oc)
                if (l != o->len)
                        bad |= 0x100;
 
-               if(bad) {
-                       o->exp.ttl = -1;
-                       so->ttl = 0;
-               }
+               if(bad)
+                       EXP_Clr(&oc->exp);
 
                sg->nfixed++;
                ds->n_object++;
@@ -473,7 +473,8 @@ smp_oc_getobj(struct dstat *ds, struct objcore *oc)
                oc->flags &= ~OC_F_NEEDFIXUP;
        }
        Lck_Unlock(&sg->sc->mtx);
-       EXP_Rearm(o, NAN, NAN, NAN, NAN);       // XXX: Shouldn't be needed
+       if (bad)
+               EXP_Rearm(oc, NAN, NAN, NAN, NAN);
        return (o);
 }
 
@@ -496,16 +497,16 @@ smp_oc_updatemeta(struct objcore *oc)
                /* Lock necessary, we might race close_seg */
                Lck_Lock(&sg->sc->mtx);
                so->ban = BAN_Time(oc->ban);
-               so->ttl = oc->timer_when;
+               so->exp = oc->exp;
                Lck_Unlock(&sg->sc->mtx);
        } else {
                so->ban = BAN_Time(oc->ban);
-               so->ttl = oc->timer_when;
+               so->exp = oc->exp;
        }
 }
 
 static void __match_proto__()
-smp_oc_freeobj(struct objcore *oc)
+smp_oc_freeobj(struct dstat *ds, struct objcore *oc)
 {
        struct smp_seg *sg;
        struct smp_object *so;
@@ -516,13 +517,18 @@ smp_oc_freeobj(struct objcore *oc)
        so = smp_find_so(sg, oc->priv2);
 
        Lck_Lock(&sg->sc->mtx);
-       so->ttl = 0;
+       EXP_Clr(&so->exp);
        so->ptr = 0;
 
        assert(sg->nobj > 0);
-       assert(sg->nfixed > 0);
        sg->nobj--;
-       sg->nfixed--;
+       if (oc->flags & OC_F_NEEDFIXUP)
+               ds->n_vampireobject--;
+       else {
+               assert(sg->nfixed > 0);
+               sg->nfixed--;
+               ds->n_object--;
+       }
 
        Lck_Unlock(&sg->sc->mtx);
 }
diff --git a/include/persistent.h b/include/persistent.h
index f0cb7f5..0c48154 100644
--- a/include/persistent.h
+++ b/include/persistent.h
@@ -131,14 +131,11 @@ struct smp_segptr {
 
 /*
  * An object descriptor
- *
- * A positive ttl is obj.ttl with obj.grace being NAN
- * A negative ttl is - (obj.ttl + obj.grace)
  */
 
 struct smp_object {
        uint8_t                 hash[32];       /* really: DIGEST_LEN */
-       double                  ttl;
+       struct exp              exp;
        double                  ban;
        uint64_t                ptr;            /* rel to silo */
 };
-- 
2.0.0.rc0


_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to