[master] af2fb99 Collect all the LRU stuff in its own source file.

Poul-Henning Kamp phk at FreeBSD.org
Thu Feb 4 00:20:26 CET 2016


commit af2fb997eeef79db5f8d09b8a3a73aefe7920dce
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Feb 3 23:20:02 2016 +0000

    Collect all the LRU stuff in its own source file.

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index 6bb046c..5c84034 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -86,6 +86,7 @@ varnishd_SOURCES = \
 	storage/mgt_stevedore.c \
 	storage/stevedore_utils.c \
 	storage/storage_file.c \
+	storage/storage_lru.c \
 	storage/storage_malloc.c \
 	storage/storage_persistent.c \
 	storage/mgt_storage_persistent.c \
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index a52434d..dc08c24 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -354,15 +354,6 @@ struct worker {
 	uintptr_t		stack_end;
 };
 
-/* LRU ---------------------------------------------------------------*/
-
-struct lru {
-	unsigned		magic;
-#define LRU_MAGIC		0x3fec7bb0
-	VTAILQ_HEAD(,objcore)	lru_head;
-	struct lock		mtx;
-};
-
 /* Stored object -----------------------------------------------------
  * This is just to encapsulate the fields owned by the stevedore
  */
diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c
index fa2d56c..5c20011 100644
--- a/bin/varnishd/storage/stevedore.c
+++ b/bin/varnishd/storage/stevedore.c
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 
 #include "cache/cache.h"
+#include "hash/hash_slinger.h"
 
 #include "storage/storage.h"
 #include "vrt.h"
@@ -45,29 +46,6 @@
 static const struct stevedore * volatile stv_next;
 
 /*--------------------------------------------------------------------
- */
-
-struct lru *
-LRU_Alloc(void)
-{
-	struct lru *l;
-
-	ALLOC_OBJ(l, LRU_MAGIC);
-	AN(l);
-	VTAILQ_INIT(&l->lru_head);
-	Lck_New(&l->mtx, lck_lru);
-	return (l);
-}
-
-void
-LRU_Free(struct lru *lru)
-{
-	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
-	Lck_Delete(&lru->mtx);
-	FREE_OBJ(lru);
-}
-
-/*--------------------------------------------------------------------
  * XXX: trust pointer writes to be atomic
  */
 
@@ -101,7 +79,6 @@ stv_pick_stevedore(struct vsl_log *vsl, const char **hint)
 	return (stv);
 }
 
-
 /*-------------------------------------------------------------------
  * Allocate storage for an object, based on the header information.
  * XXX: If we know (a hint of) the length, we could allocate space
diff --git a/bin/varnishd/storage/storage.h b/bin/varnishd/storage/storage.h
index ac4b485..d63b82b 100644
--- a/bin/varnishd/storage/storage.h
+++ b/bin/varnishd/storage/storage.h
@@ -120,8 +120,12 @@ uintmax_t STV_FileSize(int fd, const char *size, unsigned *granularity,
     const char *ctx);
 
 struct lru *LRU_Alloc(void);
-void LRU_Free(struct lru *lru);
-int EXP_NukeOne(struct worker *wrk, struct lru *lru);
+void LRU_Free(struct lru *);
+void LRU_Add(struct objcore *);
+void LRU_Remove(struct objcore *);
+int LRU_NukeOne(struct worker *, struct lru *);
+void LRU_Touch(struct worker *, struct objcore *, double now);
+
 
 /*--------------------------------------------------------------------*/
 extern const struct stevedore sma_stevedore;
diff --git a/bin/varnishd/storage/storage_lru.c b/bin/varnishd/storage/storage_lru.c
new file mode 100644
index 0000000..0acb91d
--- /dev/null
+++ b/bin/varnishd/storage/storage_lru.c
@@ -0,0 +1,184 @@
+/*-
+ * Copyright (c) 2007-2015 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Dag-Erling Smørgav <des at des.no>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * STEVEDORE: one who works at or is responsible for loading and
+ * unloading ships in port.  Example: "on the wharves, stevedores were
+ * unloading cargo from the far corners of the world." Origin: Spanish
+ * estibador, from estibar to pack.  First Known Use: 1788
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cache/cache.h"
+#include "hash/hash_slinger.h"
+
+#include "storage/storage.h"
+#include "vtim.h"
+
+struct lru {
+	unsigned		magic;
+#define LRU_MAGIC		0x3fec7bb0
+	VTAILQ_HEAD(,objcore)	lru_head;
+	struct lock		mtx;
+};
+
+struct lru *
+LRU_Alloc(void)
+{
+	struct lru *l;
+
+	ALLOC_OBJ(l, LRU_MAGIC);
+	AN(l);
+	VTAILQ_INIT(&l->lru_head);
+	Lck_New(&l->mtx, lck_lru);
+	return (l);
+}
+
+void
+LRU_Free(struct lru *lru)
+{
+	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
+	Lck_Delete(&lru->mtx);
+	FREE_OBJ(lru);
+}
+
+void
+LRU_Add(struct objcore *oc)
+{
+	struct lru *lru;
+
+	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+	lru = ObjGetLRU(oc);
+	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
+	Lck_Lock(&lru->mtx);
+	VTAILQ_INSERT_TAIL(&lru->lru_head, oc, lru_list);
+	oc->last_lru = VTIM_real();
+	Lck_Unlock(&lru->mtx);
+}
+
+void
+LRU_Remove(struct objcore *oc)
+{
+	struct lru *lru;
+
+	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+	lru = ObjGetLRU(oc);
+	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
+	Lck_Lock(&lru->mtx);
+	if (!isnan(oc->last_lru)) {
+		VTAILQ_REMOVE(&lru->lru_head, oc, lru_list);
+		oc->last_lru = NAN;
+	}
+	Lck_Unlock(&lru->mtx);
+}
+
+void __match_proto__(objtouch_f)
+LRU_Touch(struct worker *wrk, struct objcore *oc, double now)
+{
+	struct lru *lru;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+
+	/*
+	 * To avoid the exphdl->mtx becoming a hotspot, we only
+	 * attempt to move objects if they have not been moved
+	 * recently and if the lock is available.  This optimization
+	 * obviously leaves the LRU list imperfectly sorted.
+	 */
+
+	if (oc->flags & OC_F_INCOMPLETE)
+		return;
+
+	if (now - oc->last_lru < cache_param->lru_interval)
+		return;
+
+	lru = ObjGetLRU(oc);
+	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
+
+	if (Lck_Trylock(&lru->mtx))
+		return;
+
+	if (!isnan(oc->last_lru)) {
+		/* Can only touch it while it's actually on the LRU list */
+		VTAILQ_REMOVE(&lru->lru_head, oc, lru_list);
+		VTAILQ_INSERT_TAIL(&lru->lru_head, oc, lru_list);
+		VSC_C_main->n_lru_moved++;
+		oc->last_lru = now;
+	}
+	Lck_Unlock(&lru->mtx);
+}
+
+/*--------------------------------------------------------------------
+ * Attempt to make space by nuking the oldest object on the LRU list
+ * which isn't in use.
+ * Returns: 1: did, 0: didn't, -1: can't
+ */
+
+int
+LRU_NukeOne(struct worker *wrk, struct lru *lru)
+{
+	struct objcore *oc, *oc2;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
+	/* Find the first currently unused object on the LRU.  */
+	Lck_Lock(&lru->mtx);
+	VTAILQ_FOREACH_SAFE(oc, &lru->lru_head, lru_list, oc2) {
+		CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+
+		VSLb(wrk->vsl, SLT_ExpKill, "LRU_Cand p=%p f=0x%x r=%d",
+		    oc, oc->flags, oc->refcnt);
+
+		AZ(isnan(oc->last_lru));
+
+		if (ObjSnipe(wrk, oc)) {
+			VSC_C_main->n_lru_nuked++; // XXX per lru ?
+			VTAILQ_REMOVE(&lru->lru_head, oc, lru_list);
+			oc->last_lru = NAN;
+			break;
+		}
+	}
+	Lck_Unlock(&lru->mtx);
+
+	if (oc == NULL) {
+		VSLb(wrk->vsl, SLT_ExpKill, "LRU_Fail");
+		return (-1);
+	}
+
+	/* XXX: We could grab and return one storage segment to our caller */
+	ObjSlim(wrk, oc);
+
+	EXP_Poke(oc);
+
+	VSLb(wrk->vsl, SLT_ExpKill, "LRU x=%u", ObjGetXID(wrk, oc));
+	(void)HSH_DerefObjCore(wrk, &oc);
+	return (1);
+}
diff --git a/bin/varnishd/storage/storage_persistent.c b/bin/varnishd/storage/storage_persistent.c
index c068a44..735c7c5 100644
--- a/bin/varnishd/storage/storage_persistent.c
+++ b/bin/varnishd/storage/storage_persistent.c
@@ -235,7 +235,7 @@ smp_open_segs(struct smp_sc *sc, struct smp_signspace *spc)
 		ALLOC_OBJ(sg, SMP_SEG_MAGIC);
 		AN(sg);
 		sg->lru = LRU_Alloc();
-		CHECK_OBJ_NOTNULL(sg->lru, LRU_MAGIC);
+		AN(sg->lru);
 		sg->p = *ss;
 
 		sg->flags |= SMP_SEG_MUSTLOAD;
@@ -531,7 +531,7 @@ smp_allocobj(struct worker *wrk, const struct stevedore *stv,
 
 	while (1) {
 		if (really > 0) {
-			if (EXP_NukeOne(wrk, stv->lru) == -1)
+			if (LRU_NukeOne(wrk, stv->lru) == -1)
 				return (0);
 			really--;
 		}
@@ -608,10 +608,9 @@ const struct stevedore smp_stevedore = {
  */
 
 static void
-debug_report_silo(struct cli *cli, const struct smp_sc *sc, int objs)
+debug_report_silo(struct cli *cli, const struct smp_sc *sc)
 {
 	struct smp_seg *sg;
-	struct objcore *oc;
 
 	VCLI_Out(cli, "Silo: %s (%s)\n",
 	    sc->stevedore->ident, sc->filename);
@@ -626,10 +625,6 @@ debug_report_silo(struct cli *cli, const struct smp_sc *sc, int objs)
 			   (uintmax_t)(sc->next_top - sc->next_bot));
 		VCLI_Out(cli, "    %u nobj, %u alloc, %u lobjlist, %u fixed\n",
 		    sg->nobj, sg->nalloc, sg->p.lobjlist, sg->nfixed);
-		if (objs) {
-			VTAILQ_FOREACH(oc, &sg->lru->lru_head, lru_list)
-				VCLI_Out(cli, "      OC %p\n", oc);
-		}
 	}
 }
 
@@ -642,7 +637,7 @@ debug_persistent(struct cli *cli, const char * const * av, void *priv)
 
 	if (av[2] == NULL) {
 		VTAILQ_FOREACH(sc, &silos, list)
-			debug_report_silo(cli, sc, 0);
+			debug_report_silo(cli, sc);
 		return;
 	}
 	VTAILQ_FOREACH(sc, &silos, list)
@@ -654,7 +649,7 @@ debug_persistent(struct cli *cli, const char * const * av, void *priv)
 		return;
 	}
 	if (av[3] == NULL) {
-		debug_report_silo(cli, sc, 0);
+		debug_report_silo(cli, sc);
 		return;
 	}
 	Lck_Lock(&sc->mtx);
@@ -663,7 +658,7 @@ debug_persistent(struct cli *cli, const char * const * av, void *priv)
 			smp_close_seg(sc, sc->cur_seg);
 		smp_new_seg(sc);
 	} else if (!strcmp(av[3], "dump")) {
-		debug_report_silo(cli, sc, 1);
+		debug_report_silo(cli, sc);
 	} else {
 		VCLI_Out(cli, "Unknown operation\n");
 		VCLI_SetResult(cli, CLIS_PARAM);
diff --git a/bin/varnishd/storage/storage_persistent_silo.c b/bin/varnishd/storage/storage_persistent_silo.c
index 3b125d1..a0723bd 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -139,7 +139,6 @@ smp_load_seg(struct worker *wrk, const struct smp_sc *sc,
 	ASSERT_SILO_THREAD(sc);
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(sg, SMP_SEG_MAGIC);
-	CHECK_OBJ_NOTNULL(sg->lru, LRU_MAGIC);
 	assert(sg->flags & SMP_SEG_MUSTLOAD);
 	sg->flags &= ~SMP_SEG_MUSTLOAD;
 	AN(sg->p.offset);
@@ -225,7 +224,7 @@ smp_new_seg(struct smp_sc *sc)
 		return;
 	*sg = tmpsg;
 	sg->lru = LRU_Alloc();
-	CHECK_OBJ_NOTNULL(sg->lru, LRU_MAGIC);
+	AN(sg->lru);
 
 	sg->p.offset = IRNUP(sc, sg->p.offset);
 	sg->p.length -= sg->p.offset - tmpsg.p.offset;
diff --git a/bin/varnishd/storage/storage_simple.c b/bin/varnishd/storage/storage_simple.c
index 35cf916..95f4c05 100644
--- a/bin/varnishd/storage/storage_simple.c
+++ b/bin/varnishd/storage/storage_simple.c
@@ -39,56 +39,6 @@
 #include "storage/storage.h"
 #include "storage/storage_simple.h"
 
-#include "vtim.h"
-
-/*--------------------------------------------------------------------
- * Attempt to make space by nuking the oldest object on the LRU list
- * which isn't in use.
- * Returns: 1: did, 0: didn't, -1: can't
- */
-
-int
-EXP_NukeOne(struct worker *wrk, struct lru *lru)
-{
-	struct objcore *oc, *oc2;
-
-	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
-	/* Find the first currently unused object on the LRU.  */
-	Lck_Lock(&lru->mtx);
-	VTAILQ_FOREACH_SAFE(oc, &lru->lru_head, lru_list, oc2) {
-		CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-
-		VSLb(wrk->vsl, SLT_ExpKill, "LRU_Cand p=%p f=0x%x r=%d",
-		    oc, oc->flags, oc->refcnt);
-
-		AZ(isnan(oc->last_lru));
-
-		if (ObjSnipe(wrk, oc)) {
-			VSC_C_main->n_lru_nuked++; // XXX per lru ?
-			VTAILQ_REMOVE(&lru->lru_head, oc, lru_list);
-			oc->last_lru = NAN;
-			break;
-		}
-	}
-	Lck_Unlock(&lru->mtx);
-
-	if (oc == NULL) {
-		VSLb(wrk->vsl, SLT_ExpKill, "LRU_Fail");
-		return (-1);
-	}
-
-	/* XXX: We could grab and return one storage segment to our caller */
-	ObjSlim(wrk, oc);
-
-	EXP_Poke(oc);
-
-	VSLb(wrk->vsl, SLT_ExpKill, "LRU x=%u", ObjGetXID(wrk, oc));
-	(void)HSH_DerefObjCore(wrk, &oc);
-	return (1);
-}
-
-
 /*-------------------------------------------------------------------*/
 
 static struct storage *
@@ -178,7 +128,7 @@ SML_allocobj(struct worker *wrk, const struct stevedore *stv,
 	ltot = sizeof(struct object) + PRNDUP(wsl);
 	while (1) {
 		if (really > 0) {
-			if (EXP_NukeOne(wrk, stv->lru) == -1)
+			if (LRU_NukeOne(wrk, stv->lru) == -1)
 				return (0);
 			really--;
 		}
@@ -249,7 +199,6 @@ static void __match_proto__(objfree_f)
 sml_objfree(struct worker *wrk, struct objcore *oc)
 {
 	struct object *o;
-	struct lru *lru;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
@@ -257,14 +206,7 @@ sml_objfree(struct worker *wrk, struct objcore *oc)
 	CAST_OBJ_NOTNULL(o, oc->stobj->priv, OBJECT_MAGIC);
 	o->magic = 0;
 
-	lru = ObjGetLRU(oc);
-	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
-	Lck_Lock(&lru->mtx);
-	if (!isnan(oc->last_lru)) {
-		VTAILQ_REMOVE(&lru->lru_head, oc, lru_list);
-		oc->last_lru = NAN;
-	}
-	Lck_Unlock(&lru->mtx);
+	LRU_Remove(oc);
 
 	sml_stv_free(oc->stobj->stevedore, o->objstore);
 
@@ -397,7 +339,7 @@ objallocwithnuke(struct worker *wrk, const struct stevedore *stv, size_t size)
 
 		/* no luck; try to free some space and keep trying */
 		if (fail < cache_param->nuke_limit &&
-		    EXP_NukeOne(wrk, stv->lru) == -1)
+		    LRU_NukeOne(wrk, stv->lru) == -1)
 			break;
 	}
 	CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
@@ -548,7 +490,6 @@ sml_stable(struct worker *wrk, struct objcore *oc, struct boc *boc)
 {
 	const struct stevedore *stv;
 	struct storage *st;
-	struct lru *lru;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
@@ -564,12 +505,7 @@ sml_stable(struct worker *wrk, struct objcore *oc, struct boc *boc)
 		sml_stv_free(stv, st);
 	}
 
-	lru = ObjGetLRU(oc);
-	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
-	Lck_Lock(&lru->mtx);
-	VTAILQ_INSERT_TAIL(&lru->lru_head, oc, lru_list);
-	oc->last_lru = VTIM_real();
-	Lck_Unlock(&lru->mtx);
+	LRU_Add(oc);
 }
 
 static void * __match_proto__(objgetattr_f)
@@ -675,45 +611,6 @@ sml_setattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
 	return (retval);
 }
 
-static void __match_proto__(objtouch_f)
-sml_touch(struct worker *wrk, struct objcore *oc, double now)
-{
-	struct lru *lru;
-
-	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-
-	/*
-	 * To avoid the exphdl->mtx becoming a hotspot, we only
-	 * attempt to move objects if they have not been moved
-	 * recently and if the lock is available.  This optimization
-	 * obviously leaves the LRU list imperfectly sorted.
-	 */
-
-	if (oc->flags & OC_F_INCOMPLETE)
-		return;
-
-	if (now - oc->last_lru < cache_param->lru_interval)
-		return;
-
-	lru = ObjGetLRU(oc);
-	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
-
-	if (Lck_Trylock(&lru->mtx))
-		return;
-
-	AN(oc->exp_flags & OC_EF_EXP);
-
-	if (!isnan(oc->last_lru)) {
-		/* Can only touch it while it's actually on the LRU list */
-		VTAILQ_REMOVE(&lru->lru_head, oc, lru_list);
-		VTAILQ_INSERT_TAIL(&lru->lru_head, oc, lru_list);
-		VSC_C_main->n_lru_moved++;
-		oc->last_lru = now;
-	}
-	Lck_Unlock(&lru->mtx);
-}
-
 const struct obj_methods SML_methods = {
 	.objfree	= sml_objfree,
 	.objgetlru	= sml_objgetlru,
@@ -726,5 +623,5 @@ const struct obj_methods SML_methods = {
 	.objslim	= sml_slim,
 	.objgetattr	= sml_getattr,
 	.objsetattr	= sml_setattr,
-	.objtouch	= sml_touch,
+	.objtouch	= LRU_Touch,
 };



More information about the varnish-commit mailing list