[master] 56c38b6 Make HSH_Insert() more like HSH_Unbusy()

Martin Blix Grydeland martin at varnish-software.com
Tue Feb 23 17:44:47 CET 2016


commit 56c38b6456e185409bd3c82173a3fda97933a98a
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date:   Tue Feb 23 16:39:43 2016 +0100

    Make HSH_Insert() more like HSH_Unbusy()
    
    HSH_Insert() needs to take the same precautions as HSH_Unbusy() in
    order to not race against e.g. the ban lurker. In order to do this, we
    pass it the ban that the objcore should be associated with, and it
    will take care of calling BAN_RefBan() correctly.

diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c
index 4ff82be..90fbb25 100644
--- a/bin/varnishd/cache/cache_hash.c
+++ b/bin/varnishd/cache/cache_hash.c
@@ -65,6 +65,8 @@
 static const struct hash_slinger *hash;
 static struct objhead *private_oh;
 
+static void hsh_rush(struct worker *wrk, struct objhead *oh);
+
 /*---------------------------------------------------------------------*/
 
 static struct objhead *
@@ -256,13 +258,16 @@ hsh_testmagic(void *result)
  */
 
 void
-HSH_Insert(struct worker *wrk, const void *digest, struct objcore *oc)
+HSH_Insert(struct worker *wrk, const void *digest, struct objcore *oc,
+    struct ban *ban)
 {
 	struct objhead *oh;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	AN(digest);
 	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+	AN(ban);
+	AZ(oc->flags & OC_F_PRIVATE);
 
 	hsh_prealloc(wrk);
 
@@ -272,13 +277,25 @@ HSH_Insert(struct worker *wrk, const void *digest, struct objcore *oc)
 	Lck_AssertHeld(&oh->mtx);
 	assert(oh->refcnt > 0);
 
-	/* Insert (precreated) objcore in objecthead */
-	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-	AZ(oc->flags & OC_F_BUSY);
+	/* Mark object busy and insert (precreated) objcore in
+	   objecthead. The new object inherits our objhead reference. */
+	oc->flags |= OC_F_BUSY;
+	oc->objhead = oh;
+	VTAILQ_INSERT_TAIL(&oh->objcs, oc, hsh_list);
+	Lck_Unlock(&oh->mtx);
+
+	BAN_RefBan(oc, ban);
+	AN(oc->ban);
+	EXP_Insert(wrk, oc);
 
+	/* Move the object first in the oh list, unbusy it and run the
+	   waitinglist if necessary */
+	Lck_Lock(&oh->mtx);
+	VTAILQ_REMOVE(&oh->objcs, oc, hsh_list);
 	VTAILQ_INSERT_HEAD(&oh->objcs, oc, hsh_list);
-	/* NB: do not deref objhead the new object inherits our reference */
-	oc->objhead = oh;
+	oc->flags &= ~OC_F_BUSY;
+	if (!VTAILQ_EMPTY(&oh->waitinglist))
+		hsh_rush(wrk, oh);
 	Lck_Unlock(&oh->mtx);
 	wrk->stats->n_objectcore++;
 	wrk->stats->n_vampireobject++;
diff --git a/bin/varnishd/hash/hash_slinger.h b/bin/varnishd/hash/hash_slinger.h
index 807c83d..b10e674 100644
--- a/bin/varnishd/hash/hash_slinger.h
+++ b/bin/varnishd/hash/hash_slinger.h
@@ -61,13 +61,15 @@ enum lookup_e {
 };
 
 /* cache_hash.c */
+struct ban;
 void HSH_Cleanup(struct worker *w);
 enum lookup_e HSH_Lookup(struct req *, struct objcore **, struct objcore **,
     int wait_for_busy, int always_insert);
 void HSH_Ref(struct objcore *o);
 void HSH_Init(const struct hash_slinger *slinger);
 void HSH_AddString(struct req *, void *ctx, const char *str);
-void HSH_Insert(struct worker *, const void *hash, struct objcore *);
+void HSH_Insert(struct worker *, const void *hash, struct objcore *,
+    struct ban *);
 void HSH_Purge(struct worker *, struct objhead *, double ttl, double grace,
     double keep);
 void HSH_config(const char *h_arg);
diff --git a/bin/varnishd/storage/storage_persistent_silo.c b/bin/varnishd/storage/storage_persistent_silo.c
index 0e1637f..1a03708 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -163,18 +163,15 @@ smp_load_seg(struct worker *wrk, const struct smp_sc *sc,
 		ban = BAN_FindBan(so->ban);
 		AN(ban);
 		oc = ObjNew(wrk);
-		oc->flags &= ~OC_F_BUSY;
 		oc->stobj->stevedore = sc->parent;
 		smp_init_oc(oc, sg, no);
 		VTAILQ_INSERT_TAIL(&sg->objcores, oc, lru_list);
 		oc->stobj->priv2 |= NEED_FIXUP;
-		BAN_RefBan(oc, ban);
-		AN(oc->ban);
 		EXP_COPY(oc, so);
 		sg->nobj++;
 		oc->refcnt++;
-		HSH_Insert(wrk, so->hash, oc);
-		EXP_Insert(wrk, oc);
+		HSH_Insert(wrk, so->hash, oc, ban);
+		AN(oc->ban);
 		HSH_DerefBoc(wrk, oc);	// XXX Keep it an stream resurrection?
 		(void)HSH_DerefObjCore(wrk, &oc);
 	}



More information about the varnish-commit mailing list