[master] 2c76f5b Collect all the stuff which implements objects on top of "simple" stevedores and call it "SML".

Poul-Henning Kamp phk at FreeBSD.org
Mon Dec 14 23:36:58 CET 2015


commit 2c76f5b2152d714f42c322041d9552d73ef597c9
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Dec 14 22:35:56 2015 +0000

    Collect all the stuff which implements objects on top of "simple"
    stevedores and call it "SML".
    
    I bet this is going to surprise Martin :-)

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index 99e7fb4..1f1f110 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -113,6 +113,7 @@ noinst_HEADERS = \
 	mgt/mgt_cli.h \
 	mgt/mgt_param.h \
 	storage/storage.h \
+	storage/storage_simple.h \
 	storage/storage_persistent.h \
 	waiter/waiter_priv.h \
 	waiter/mgt_waiter.h
diff --git a/bin/varnishd/cache/cache_obj.c b/bin/varnishd/cache/cache_obj.c
index 206cf03..cadd0f1 100644
--- a/bin/varnishd/cache/cache_obj.c
+++ b/bin/varnishd/cache/cache_obj.c
@@ -57,18 +57,6 @@ obj_getmethods(const struct objcore *oc)
 	return (oc->stobj->stevedore->methods);
 }
 
-static struct object *
-obj_getobj(struct worker *wrk, struct objcore *oc)
-{
-	const struct storeobj_methods *m;
-
-	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-	m = obj_getmethods(oc);
-	AN(m->getobj);
-	return (m->getobj(wrk, oc));
-}
-
 /*====================================================================
  * ObjIterate()
  *
@@ -78,127 +66,12 @@ int
 ObjIterate(struct worker *wrk, struct objcore *oc,
     void *priv, objiterate_f *func)
 {
-	struct busyobj *bo;
-	struct object *obj;
-	struct storage *st;
-	struct storage *checkpoint = NULL;
-	ssize_t checkpoint_len = 0;
-	ssize_t len = 0;
-	int ret = 0;
-	ssize_t ol;
-	ssize_t nl;
-	ssize_t sl;
-	void *p;
-	ssize_t l;
 	const struct storeobj_methods *om = obj_getmethods(oc);
 
-	if (om->objiterator != NULL)
-		return (om->objiterator(wrk, oc, priv, func));
-
-	obj = obj_getobj(wrk, oc);
-	CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
-
-	bo = HSH_RefBusy(oc);
-
-	if (bo == NULL) {
-		VTAILQ_FOREACH(st, &obj->list, list)
-			if (func(priv, 0, st->ptr, st->len))
-				return (-1);
-		return (0);
-	}
-
-	p = NULL;
-	l = 0;
-
-	while (1) {
-		ol = len;
-		nl = VBO_waitlen(wrk, bo, ol);
-		if (bo->state == BOS_FAILED) {
-			ret = -1;
-			break;
-		}
-		if (nl == ol) {
-			if (bo->state == BOS_FINISHED)
-				break;
-			continue;
-		}
-		Lck_Lock(&bo->mtx);
-		AZ(VTAILQ_EMPTY(&obj->list));
-		if (checkpoint == NULL) {
-			st = VTAILQ_FIRST(&obj->list);
-			sl = 0;
-		} else {
-			st = checkpoint;
-			sl = checkpoint_len;
-			ol -= checkpoint_len;
-		}
-		while (st != NULL) {
-			if (st->len > ol) {
-				p = st->ptr + ol;
-				l = st->len - ol;
-				len += l;
-				break;
-			}
-			ol -= st->len;
-			assert(ol >= 0);
-			nl -= st->len;
-			assert(nl > 0);
-			sl += st->len;
-			st = VTAILQ_NEXT(st, list);
-			if (VTAILQ_NEXT(st, list) != NULL) {
-				checkpoint = st;
-				checkpoint_len = sl;
-			}
-		}
-		CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
-		CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
-		st = VTAILQ_NEXT(st, list);
-		if (st != NULL && st->len == 0)
-			st = NULL;
-		Lck_Unlock(&bo->mtx);
-		assert(l > 0 || bo->state == BOS_FINISHED);
-		if (func(priv, st != NULL ? 0 : 1, p, l)) {
-			ret = -1;
-			break;
-		}
-	}
-	if (oc->flags & OC_F_PASS)
-		bo->abandon = 1;
-	VBO_DerefBusyObj(wrk, &bo);
-	return (ret);
-}
-
-/*--------------------------------------------------------------------
- */
-
-static struct storage *
-objallocwithnuke(struct worker *wrk, const struct stevedore *stv, size_t size)
-{
-	struct storage *st = NULL;
-	unsigned fail;
-
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
-
-	if (size > cache_param->fetch_maxchunksize)
-		size = cache_param->fetch_maxchunksize;
-
-	assert(size <= UINT_MAX);	/* field limit in struct storage */
-
-	for (fail = 0; fail <= cache_param->nuke_limit; fail++) {
-		/* try to allocate from it */
-		AN(stv->alloc);
-		st = STV_alloc(stv, size);
-		if (st != NULL)
-			break;
-
-		/* no luck; try to free some space and keep trying */
-		if (fail < cache_param->nuke_limit &&
-		    EXP_NukeOne(wrk, stv->lru) == -1)
-			break;
-	}
-	CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
-	return (st);
+	AN(func);
+	AN(om->objiterator);
+	return (om->objiterator(wrk, oc, priv, func));
 }
 
 /*====================================================================
@@ -213,8 +86,6 @@ objallocwithnuke(struct worker *wrk, const struct stevedore *stv, size_t size)
 int
 ObjGetSpace(struct worker *wrk, struct objcore *oc, ssize_t *sz, uint8_t **ptr)
 {
-	struct object *o;
-	struct storage *st;
 	const struct storeobj_methods *om = obj_getmethods(oc);
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
@@ -222,37 +93,8 @@ ObjGetSpace(struct worker *wrk, struct objcore *oc, ssize_t *sz, uint8_t **ptr)
 	AN(ptr);
 	assert(*sz > 0);
 
-	if (om->objgetspace != NULL)
-		return (om->objgetspace(wrk, oc, sz, ptr));
-
-	o = obj_getobj(wrk, oc);
-	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-
-	st = VTAILQ_LAST(&o->list, storagehead);
-	if (st != NULL && st->len < st->space) {
-		*sz = st->space - st->len;
-		*ptr = st->ptr + st->len;
-		assert (*sz > 0);
-		return (1);
-	}
-
-	st = objallocwithnuke(wrk, oc->stobj->stevedore, *sz);
-	if (st == NULL)
-		return (0);
-
-	if (oc->busyobj != NULL) {
-		CHECK_OBJ_NOTNULL(oc->busyobj, BUSYOBJ_MAGIC);
-		Lck_Lock(&oc->busyobj->mtx);
-		VTAILQ_INSERT_TAIL(&o->list, st, list);
-		Lck_Unlock(&oc->busyobj->mtx);
-	} else {
-		AN(oc->flags & (OC_F_PRIVATE));
-		VTAILQ_INSERT_TAIL(&o->list, st, list);
-	}
-	*sz = st->space - st->len;
-	assert (*sz > 0);
-	*ptr = st->ptr + st->len;
-	return (1);
+	AN(om->objgetspace);
+	return (om->objgetspace(wrk, oc, sz, ptr));
 }
 
 /*====================================================================
@@ -265,25 +107,13 @@ ObjGetSpace(struct worker *wrk, struct objcore *oc, ssize_t *sz, uint8_t **ptr)
 void
 ObjExtend(struct worker *wrk, struct objcore *oc, ssize_t l)
 {
-	struct object *o;
-	struct storage *st;
 	const struct storeobj_methods *om = obj_getmethods(oc);
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	assert(l > 0);
 
-	if (om->objextend != NULL) {
-		om->objextend(wrk, oc, l);
-		return;
-	}
-
-	o = obj_getobj(wrk, oc);
-	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-	st = VTAILQ_LAST(&o->list, storagehead);
-	CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
-	assert(st->len + l <= st->space);
-	st->len += l;
-	o->len += l;
+	AN(om->objextend);
+	om->objextend(wrk, oc, l);
 }
 
 /*====================================================================
@@ -295,20 +125,14 @@ ObjExtend(struct worker *wrk, struct objcore *oc, ssize_t l)
 uint64_t
 ObjGetLen(struct worker *wrk, struct objcore *oc)
 {
-	struct object *o;
 	const struct storeobj_methods *om = obj_getmethods(oc);
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 
-	if (om->objgetlen != NULL)
-		return (om->objgetlen(wrk, oc));
-
-	o = obj_getobj(wrk, oc);
-	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-	return (o->len);
+	AN(om->objgetlen);
+	return (om->objgetlen(wrk, oc));
 }
 
-
 /*====================================================================
  * ObjTrimStore()
  *
@@ -319,31 +143,13 @@ ObjGetLen(struct worker *wrk, struct objcore *oc)
 void
 ObjTrimStore(struct worker *wrk, struct objcore *oc)
 {
-	const struct stevedore *stv;
-	struct storage *st;
-	struct object *o;
 	const struct storeobj_methods *om = obj_getmethods(oc);
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 
-	if (om->objtrimstore != NULL) {
+	if (om->objtrimstore != NULL)
 		om->objtrimstore(wrk, oc);
-		return;
-	}
-
-	stv = oc->stobj->stevedore;
-	CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
-	o = obj_getobj(wrk, oc);
-	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-	st = VTAILQ_LAST(&o->list, storagehead);
-	if (st == NULL)
-		return;
-	if (st->len == 0) {
-		VTAILQ_REMOVE(&o->list, st, list);
-		STV_free(stv, st);
-	} else if (st->len < st->space) {
-		STV_trim(stv, st, st->len, 1);
-	}
+	return;
 }
 
 /*====================================================================
@@ -356,32 +162,12 @@ ObjTrimStore(struct worker *wrk, struct objcore *oc)
 void
 ObjSlim(struct worker *wrk, struct objcore *oc)
 {
-	const struct stevedore *stv;
-	struct object *o;
-	struct storage *st, *stn;
 	const struct storeobj_methods *om = obj_getmethods(oc);
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 
-	if (om->objslim != NULL) {
+	if (om->objslim != NULL)
 		om->objslim(wrk, oc);
-		return;
-	}
-
-	stv = oc->stobj->stevedore;
-	CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
-	o = obj_getobj(wrk, oc);
-	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-
-	if (o->esidata != NULL) {
-		STV_free(stv, o->esidata);
-		o->esidata = NULL;
-	}
-	VTAILQ_FOREACH_SAFE(st, &o->list, list, stn) {
-		CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
-		VTAILQ_REMOVE(&o->list, st, list);
-		STV_free(stv, st);
-	}
 }
 
 /*====================================================================
@@ -393,8 +179,8 @@ ObjUpdateMeta(struct worker *wrk, struct objcore *oc)
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 
-	if (m->updatemeta != NULL)
-		m->updatemeta(wrk, oc);
+	if (m->objupdatemeta != NULL)
+		m->objupdatemeta(wrk, oc);
 }
 
 /*====================================================================
@@ -406,8 +192,8 @@ ObjFreeObj(struct worker *wrk, struct objcore *oc)
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 
-	AN(m->freeobj);
-	m->freeobj(wrk, oc);
+	AN(m->objfree);
+	m->objfree(wrk, oc);
 	AZ(oc->stobj->stevedore);
 }
 
@@ -418,8 +204,8 @@ ObjGetLRU(const struct objcore *oc)
 {
 	const struct storeobj_methods *m = obj_getmethods(oc);
 
-	AN(m->getlru);
-	return (m->getlru(oc));
+	AN(m->objgetlru);
+	return (m->objgetlru(oc));
 }
 
 /*====================================================================
@@ -432,47 +218,12 @@ void *
 ObjGetattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
    ssize_t *len)
 {
-	struct object *o;
-	ssize_t dummy;
 	const struct storeobj_methods *om = obj_getmethods(oc);
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 
-	if (om->objgetattr != NULL)
-		return (om->objgetattr(wrk, oc, attr, len));
-
-	if (len == NULL)
-		len = &dummy;
-	o = obj_getobj(wrk, oc);
-	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-	switch (attr) {
-	case OA_ESIDATA:
-		if (o->esidata == NULL)
-			return (NULL);
-		*len = o->esidata->len;
-		return (o->esidata->ptr);
-	case OA_FLAGS:
-		*len = sizeof o->oa_flags;
-		return (o->oa_flags);
-	case OA_GZIPBITS:
-		*len = sizeof o->oa_gzipbits;
-		return (o->oa_gzipbits);
-	case OA_HEADERS:
-		*len = 0;			// XXX: hack
-		return (o->oa_http);
-	case OA_LASTMODIFIED:
-		*len = sizeof o->oa_lastmodified;
-		return (o->oa_lastmodified);
-	case OA_VARY:
-		*len = 4;			// XXX: hack
-		return (o->oa_vary);
-	case OA_VXID:
-		*len = sizeof o->oa_vxid;
-		return (o->oa_vxid);
-	default:
-		break;
-	}
-	WRONG("Unsupported OBJ_ATTR");
+	AN(om->objgetattr);
+	return (om->objgetattr(wrk, oc, attr, len));
 }
 
 /*====================================================================
@@ -486,64 +237,12 @@ void *
 ObjSetattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
     ssize_t len, const void *ptr)
 {
-	struct object *o;
-	void *retval = NULL;
-	struct storage *st;
 	const struct storeobj_methods *om = obj_getmethods(oc);
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 
-	if (om->objsetattr != NULL)
-		return (om->objsetattr(wrk, oc, attr, len, ptr));
-
-	o = obj_getobj(wrk, oc);
-	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-	st = o->objstore;
-	switch (attr) {
-	case OA_ESIDATA:
-		o->esidata = objallocwithnuke(wrk, oc->stobj->stevedore, len);
-		if (o->esidata == NULL)
-			return (NULL);
-		o->esidata->len = len;
-		retval  = o->esidata->ptr;
-		break;
-	case OA_FLAGS:
-		assert(len == sizeof o->oa_flags);
-		retval = o->oa_flags;
-		break;
-	case OA_GZIPBITS:
-		assert(len == sizeof o->oa_gzipbits);
-		retval = o->oa_gzipbits;
-		break;
-	case OA_HEADERS:
-		len = PRNDUP(len);
-		assert(st->len + len <= st->space);
-		o->oa_http = (void*)(st->ptr + st->len);
-		st->len += len;
-		retval = o->oa_http;
-		break;
-	case OA_LASTMODIFIED:
-		assert(len == sizeof o->oa_lastmodified);
-		retval = o->oa_lastmodified;
-		break;
-	case OA_VARY:
-		len = PRNDUP(len);
-		assert(st->len + len <= st->space);
-		o->oa_vary = (void*)(st->ptr + st->len);
-		st->len += len;
-		retval = o->oa_vary;
-		break;
-	case OA_VXID:
-		assert(len == sizeof o->oa_vxid);
-		retval = o->oa_vxid;
-		break;
-	default:
-		WRONG("Unsupported OBJ_ATTR");
-		break;
-	}
-	if (ptr != NULL)
-		memcpy(retval, ptr, len);
-	return (retval);
+	AN(om->objsetattr);
+	return (om->objsetattr(wrk, oc, attr, len, ptr));
 }
 
 /*====================================================================
diff --git a/bin/varnishd/storage/mgt_stevedore.c b/bin/varnishd/storage/mgt_stevedore.c
index 109290f..9852ea6 100644
--- a/bin/varnishd/storage/mgt_stevedore.c
+++ b/bin/varnishd/storage/mgt_stevedore.c
@@ -183,8 +183,8 @@ STV_Config(const char *spec)
 		ARGV_ERR("(-s%s) too many arguments\n", stv->name);
 
 	AN(stv->alloc);
-	if (stv->allocobj == NULL)
-		stv->allocobj = stv_default_allocobj;
+	AN(stv->allocobj);
+	AN(stv->methods);
 
 	if (!strcmp(stv->ident, TRANSIENT_STORAGE)) {
 		stv->transient = 1;
diff --git a/bin/varnishd/storage/mgt_storage_persistent.c b/bin/varnishd/storage/mgt_storage_persistent.c
index 76d6436..f55d793 100644
--- a/bin/varnishd/storage/mgt_storage_persistent.c
+++ b/bin/varnishd/storage/mgt_storage_persistent.c
@@ -44,6 +44,7 @@
 
 #include "cache/cache.h"
 #include "storage/storage.h"
+#include "storage/storage_simple.h"
 
 #include "vsha256.h"
 
diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c
index 6c0ad0b..1029dd2 100644
--- a/bin/varnishd/storage/stevedore.c
+++ b/bin/varnishd/storage/stevedore.c
@@ -131,65 +131,6 @@ STV_alloc(const struct stevedore *stv, size_t size)
 	return (st);
 }
 
-/*--------------------------------------------------------------------
- * This function is called by stevedores ->allocobj() method, which
- * very often will be stv_default_allocobj() below, to convert a slab
- * of storage into object which the stevedore can then register in its
- * internal state, before returning it to STV_NewObject().
- * As you probably guessed: All this for persistence.
- */
-
-struct object *
-STV_MkObject(const struct stevedore *stv, struct objcore *oc, void *ptr)
-{
-	struct object *o;
-
-	CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
-	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-
-	assert(PAOK(ptr));
-
-	o = ptr;
-	INIT_OBJ(o, OBJECT_MAGIC);
-
-	VTAILQ_INIT(&o->list);
-
-	oc->stobj->magic = STOREOBJ_MAGIC;
-	oc->stobj->stevedore = stv;
-	AN(stv->methods);
-	oc->stobj->priv = o;
-	return (o);
-}
-
-/*--------------------------------------------------------------------
- * This is the default ->allocobj() which all stevedores who do not
- * implement persistent storage can rely on.
- */
-
-int
-stv_default_allocobj(const struct stevedore *stv, struct objcore *oc,
-    unsigned wsl)
-{
-	struct object *o;
-	struct storage *st;
-	unsigned ltot;
-
-	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-	ltot = sizeof(struct object) + PRNDUP(wsl);
-	st = stv->alloc(stv, ltot);
-	if (st == NULL)
-		return (0);
-	if (st->space < ltot) {
-		stv->free(st);
-		return (0);
-	}
-	o = STV_MkObject(stv, oc, st->ptr);
-	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-	st->len = sizeof(*o);
-	o->objstore = st;
-	return (1);
-}
-
 /*-------------------------------------------------------------------
  * 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 f6636ee..a42a9cb 100644
--- a/bin/varnishd/storage/storage.h
+++ b/bin/varnishd/storage/storage.h
@@ -55,46 +55,17 @@ struct storage {
 	unsigned		space;
 };
 
-/* Object ------------------------------------------------------------*/
-
-VTAILQ_HEAD(storagehead, storage);
-
-struct object {
-	unsigned		magic;
-#define OBJECT_MAGIC		0x32851d42
-	struct storage		*objstore;
-
-	char			oa_vxid[4];
-	uint8_t			*oa_vary;
-	uint8_t			*oa_http;
-	uint8_t			oa_flags[1];
-	char			oa_gzipbits[32];
-	char			oa_lastmodified[8];
-
-	struct storagehead	list;
-	ssize_t			len;
-
-	struct storage		*esidata;
-};
-
 /* Methods on objcore ------------------------------------------------*/
 
 #ifdef VARNISH_CACHE_CHILD
 
-typedef void updatemeta_f(struct worker *, struct objcore *oc);
-typedef void freeobj_f(struct worker *, struct objcore *oc);
-typedef struct lru *getlru_f(const struct objcore *oc);
-
-/*
- * Stevedores can either be simple, and provide just this method:
- */
+typedef void objupdatemeta_f(struct worker *, struct objcore *oc);
+typedef void objfree_f(struct worker *, struct objcore *oc);
+typedef struct lru *objgetlru_f(const struct objcore *oc);
 
-typedef struct object *getobj_f(struct worker *, struct objcore *oc);
+/* This method is only used by SML (...to get to persistent) */
+typedef struct object *sml_getobj_f(struct worker *, struct objcore *oc);
 
-/*
- * Or the can be "complex" and provide all of these methods:
- * (Described in comments in cache_obj.c)
- */
 typedef int objiterator_f(struct worker *, struct objcore *oc,
     void *priv, objiterate_f *func);
 typedef int objgetspace_f(struct worker *, struct objcore *,
@@ -109,11 +80,11 @@ typedef void *objsetattr_f(struct worker *, struct objcore *,
 typedef uint64_t objgetlen_f(struct worker *, struct objcore *);
 
 struct storeobj_methods {
-	freeobj_f	*freeobj;
-	getlru_f	*getlru;
-	updatemeta_f	*updatemeta;
+	objfree_f	*objfree;
+	objgetlru_f	*objgetlru;
+	objupdatemeta_f	*objupdatemeta;
 
-	getobj_f	*getobj;
+	sml_getobj_f	*sml_getobj;
 
 	objiterator_f	*objiterator;
 	objgetspace_f	*objgetspace;
@@ -152,10 +123,6 @@ typedef void storage_banexport_f(const struct stevedore *, const uint8_t *bans,
 #include "tbl/vrt_stv_var.h"
 #undef VRTSTVTYPE
 
-extern storage_allocobj_f stv_default_allocobj;
-
-extern const struct storeobj_methods default_oc_methods;
-
 /*--------------------------------------------------------------------*/
 
 struct stevedore {
@@ -199,8 +166,6 @@ extern struct stevedore *stv_transient;
 int STV_GetFile(const char *fn, int *fdp, const char **fnp, const char *ctx);
 uintmax_t STV_FileSize(int fd, const char *size, unsigned *granularity,
     const char *ctx);
-struct object *STV_MkObject(const struct stevedore *, struct objcore *,
-    void *ptr);
 
 struct lru *LRU_Alloc(void);
 void LRU_Free(struct lru *lru);
diff --git a/bin/varnishd/storage/storage_file.c b/bin/varnishd/storage/storage_file.c
index 151f75e..c1d7992 100644
--- a/bin/varnishd/storage/storage_file.c
+++ b/bin/varnishd/storage/storage_file.c
@@ -39,6 +39,7 @@
 
 #include "cache/cache.h"
 #include "storage/storage.h"
+#include "storage/storage_simple.h"
 
 #include "vnum.h"
 #include "vfil.h"
@@ -535,7 +536,8 @@ const struct stevedore smf_stevedore = {
 	.alloc		=	smf_alloc,
 	.trim		=	smf_trim,
 	.free		=	smf_free,
-	.methods	=	&default_oc_methods,
+	.allocobj	=	SML_allocobj,
+	.methods	=	&SML_methods,
 };
 
 #ifdef INCLUDE_TEST_DRIVER
diff --git a/bin/varnishd/storage/storage_malloc.c b/bin/varnishd/storage/storage_malloc.c
index ce6b0c2..d7d4561 100644
--- a/bin/varnishd/storage/storage_malloc.c
+++ b/bin/varnishd/storage/storage_malloc.c
@@ -36,6 +36,7 @@
 
 #include "cache/cache.h"
 #include "storage/storage.h"
+#include "storage/storage_simple.h"
 
 #include "vnum.h"
 
@@ -251,7 +252,8 @@ const struct stevedore sma_stevedore = {
 	.alloc		=	sma_alloc,
 	.free		=	sma_free,
 	.trim		=	sma_trim,
-	.methods	=	&default_oc_methods,
+	.allocobj	=	SML_allocobj,
+	.methods	=	&SML_methods,
 	.var_free_space =	sma_free_space,
 	.var_used_space =	sma_used_space,
 };
diff --git a/bin/varnishd/storage/storage_persistent.c b/bin/varnishd/storage/storage_persistent.c
index b87fece..a71f150 100644
--- a/bin/varnishd/storage/storage_persistent.c
+++ b/bin/varnishd/storage/storage_persistent.c
@@ -44,6 +44,7 @@
 
 #include "cache/cache.h"
 #include "storage/storage.h"
+#include "storage/storage_simple.h"
 
 #include "hash/hash_slinger.h"
 #include "vcli.h"
@@ -53,6 +54,8 @@
 
 #include "storage/storage_persistent.h"
 
+static struct storeobj_methods smp_oc_realmethods;
+
 /*--------------------------------------------------------------------*/
 
 /*
@@ -526,7 +529,7 @@ smp_allocobj(const struct stevedore *stv, struct objcore *oc, unsigned wsl)
 
 	assert(st->space >= ltot);
 
-	o = STV_MkObject(stv, oc, st->ptr);
+	o = SML_MkObject(stv, oc, st->ptr);
 	AN(oc->stobj->stevedore);
 	assert(oc->stobj->stevedore == stv);
 	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
@@ -592,7 +595,7 @@ const struct stevedore smp_stevedore = {
 	.signal_close = smp_signal_close,
 	.baninfo =	smp_baninfo,
 	.banexport =	smp_banexport,
-	.methods =	&smp_oc_methods,
+	.methods =	&smp_oc_realmethods,
 };
 
 /*--------------------------------------------------------------------
@@ -682,6 +685,11 @@ void
 SMP_Init(void)
 {
 	CLI_AddFuncs(debug_cmds);
+	smp_oc_realmethods = SML_methods;
+	smp_oc_realmethods.sml_getobj = smp_oc_methods.sml_getobj;
+	smp_oc_realmethods.objupdatemeta =	smp_oc_methods.objupdatemeta;
+	smp_oc_realmethods.objfree = smp_oc_methods.objfree;
+	smp_oc_realmethods.objgetlru = smp_oc_methods.objgetlru;
 }
 
 /*--------------------------------------------------------------------
diff --git a/bin/varnishd/storage/storage_persistent_silo.c b/bin/varnishd/storage/storage_persistent_silo.c
index ab604d8..8b370c6 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -40,6 +40,7 @@
 
 #include "cache/cache.h"
 #include "storage/storage.h"
+#include "storage/storage_simple.h"
 
 #include "hash/hash_slinger.h"
 #include "vsha256.h"
@@ -387,7 +388,7 @@ smp_loaded_st(const struct smp_sc *sc, const struct smp_seg *sg,
  */
 
 static struct object *
-smp_oc_getobj(struct worker *wrk, struct objcore *oc)
+smp_oc_sml_getobj(struct worker *wrk, struct objcore *oc)
 {
 	struct object *o;
 	struct smp_seg *sg;
@@ -401,7 +402,7 @@ smp_oc_getobj(struct worker *wrk, struct objcore *oc)
 	AN(oc->stobj->stevedore);
 
 	/* Some calls are direct, but they should match anyway */
-	assert(oc->stobj->stevedore->methods->getobj == smp_oc_getobj);
+	assert(oc->stobj->stevedore->methods->sml_getobj == smp_oc_sml_getobj);
 
 	CAST_OBJ_NOTNULL(sg, oc->stobj->priv, SMP_SEG_MAGIC);
 	so = smp_find_so(sg, oc->stobj->priv2);
@@ -455,7 +456,7 @@ smp_oc_getobj(struct worker *wrk, struct objcore *oc)
 }
 
 static void
-smp_oc_updatemeta(struct worker *wrk, struct objcore *oc)
+smp_oc_objupdatemeta(struct worker *wrk, struct objcore *oc)
 {
 	struct object *o;
 	struct smp_seg *sg;
@@ -463,7 +464,7 @@ smp_oc_updatemeta(struct worker *wrk, struct objcore *oc)
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-	o = smp_oc_getobj(wrk, oc);
+	o = smp_oc_sml_getobj(wrk, oc);
 	AN(o);
 
 	CAST_OBJ_NOTNULL(sg, oc->stobj->priv, SMP_SEG_MAGIC);
@@ -482,8 +483,8 @@ smp_oc_updatemeta(struct worker *wrk, struct objcore *oc)
 	}
 }
 
-static void __match_proto__(freeobj_f)
-smp_oc_freeobj(struct worker *wrk, struct objcore *oc)
+static void __match_proto__(objfree_f)
+smp_oc_objfree(struct worker *wrk, struct objcore *oc)
 {
 	struct smp_seg *sg;
 	struct smp_object *so;
@@ -516,8 +517,8 @@ smp_oc_freeobj(struct worker *wrk, struct objcore *oc)
  * Find the per-segment lru list for this object
  */
 
-static struct lru * __match_proto__(getlru_f)
-smp_oc_getlru(const struct objcore *oc)
+static struct lru * __match_proto__(objgetlru_f)
+smp_oc_objgetlru(const struct objcore *oc)
 {
 	struct smp_seg *sg;
 
@@ -526,10 +527,10 @@ smp_oc_getlru(const struct objcore *oc)
 }
 
 const struct storeobj_methods smp_oc_methods = {
-	.getobj =		smp_oc_getobj,
-	.updatemeta =		smp_oc_updatemeta,
-	.freeobj =		smp_oc_freeobj,
-	.getlru =		smp_oc_getlru,
+	.sml_getobj =		smp_oc_sml_getobj,
+	.objupdatemeta =		smp_oc_objupdatemeta,
+	.objfree =		smp_oc_objfree,
+	.objgetlru =		smp_oc_objgetlru,
 };
 
 /*--------------------------------------------------------------------*/
diff --git a/bin/varnishd/storage/storage_simple.c b/bin/varnishd/storage/storage_simple.c
index 141b413..b8eedec 100644
--- a/bin/varnishd/storage/storage_simple.c
+++ b/bin/varnishd/storage/storage_simple.c
@@ -33,27 +33,92 @@
 #include <stdlib.h>
 
 #include "cache/cache.h"
+#include "hash/hash_slinger.h"
 
 #include "storage/storage.h"
+#include "storage/storage_simple.h"
+
+/*--------------------------------------------------------------------
+ * This function is called by stevedores ->allocobj() method, which
+ * very often will be SML_allocobj() below, to convert a slab
+ * of storage into object which the stevedore can then register in its
+ * internal state, before returning it to STV_NewObject().
+ * As you probably guessed: All this for persistence.
+ */
+
+struct object *
+SML_MkObject(const struct stevedore *stv, struct objcore *oc, void *ptr)
+{
+	struct object *o;
+
+	CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
+	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+
+	assert(PAOK(ptr));
+
+	o = ptr;
+	INIT_OBJ(o, OBJECT_MAGIC);
+
+	VTAILQ_INIT(&o->list);
+
+	oc->stobj->magic = STOREOBJ_MAGIC;
+	oc->stobj->stevedore = stv;
+	AN(stv->methods);
+	oc->stobj->priv = o;
+	return (o);
+}
+
+/*--------------------------------------------------------------------
+ * This is the default ->allocobj() which all stevedores who do not
+ * implement persistent storage can rely on.
+ */
+
+int
+SML_allocobj(const struct stevedore *stv, struct objcore *oc,
+    unsigned wsl)
+{
+	struct object *o;
+	struct storage *st;
+	unsigned ltot;
+
+	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+	ltot = sizeof(struct object) + PRNDUP(wsl);
+	st = stv->alloc(stv, ltot);
+	if (st == NULL)
+		return (0);
+	if (st->space < ltot) {
+		stv->free(st);
+		return (0);
+	}
+	o = SML_MkObject(stv, oc, st->ptr);
+	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
+	st->len = sizeof(*o);
+	o->objstore = st;
+	return (1);
+}
 
 /*---------------------------------------------------------------------
  */
 
-static struct object * __match_proto__(getobj_f)
-default_oc_getobj(struct worker *wrk, struct objcore *oc)
+static struct object *
+getobj(struct worker *wrk, struct objcore *oc)
 {
+	const struct storeobj_methods *m;
 	struct object *o;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+	m = oc->stobj->stevedore->methods;
+	if (m->sml_getobj != NULL)
+		return (m->sml_getobj(wrk, oc));
 	if (oc->stobj->priv == NULL)
 		return (NULL);
 	CAST_OBJ_NOTNULL(o, oc->stobj->priv, OBJECT_MAGIC);
 	return (o);
 }
 
-static void __match_proto__(freeobj_f)
-default_oc_freeobj(struct worker *wrk, struct objcore *oc)
+static void __match_proto__(objfree_f)
+sml_objfree(struct worker *wrk, struct objcore *oc)
 {
 	struct object *o;
 
@@ -71,8 +136,8 @@ default_oc_freeobj(struct worker *wrk, struct objcore *oc)
 	wrk->stats->n_object--;
 }
 
-static struct lru * __match_proto__(getlru_f)
-default_oc_getlru(const struct objcore *oc)
+static struct lru * __match_proto__(objgetlru_f)
+sml_objgetlru(const struct objcore *oc)
 {
 	const struct stevedore *stv;
 
@@ -81,8 +146,363 @@ default_oc_getlru(const struct objcore *oc)
 	return (stv->lru);
 }
 
-const struct storeobj_methods default_oc_methods = {
-	.getobj = default_oc_getobj,
-	.freeobj = default_oc_freeobj,
-	.getlru = default_oc_getlru,
+static int __match_proto__(objiterate_f)
+sml_iterator(struct worker *wrk, struct objcore *oc,
+    void *priv, objiterate_f *func)
+{
+	struct busyobj *bo;
+	struct object *obj;
+	struct storage *st;
+	struct storage *checkpoint = NULL;
+	ssize_t checkpoint_len = 0;
+	ssize_t len = 0;
+	int ret = 0;
+	ssize_t ol;
+	ssize_t nl;
+	ssize_t sl;
+	void *p;
+	ssize_t l;
+
+	obj = getobj(wrk, oc);
+	CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
+
+	bo = HSH_RefBusy(oc);
+
+	if (bo == NULL) {
+		VTAILQ_FOREACH(st, &obj->list, list)
+			if (func(priv, 0, st->ptr, st->len))
+				return (-1);
+		return (0);
+	}
+
+	p = NULL;
+	l = 0;
+
+	while (1) {
+		ol = len;
+		nl = VBO_waitlen(wrk, bo, ol);
+		if (bo->state == BOS_FAILED) {
+			ret = -1;
+			break;
+		}
+		if (nl == ol) {
+			if (bo->state == BOS_FINISHED)
+				break;
+			continue;
+		}
+		Lck_Lock(&bo->mtx);
+		AZ(VTAILQ_EMPTY(&obj->list));
+		if (checkpoint == NULL) {
+			st = VTAILQ_FIRST(&obj->list);
+			sl = 0;
+		} else {
+			st = checkpoint;
+			sl = checkpoint_len;
+			ol -= checkpoint_len;
+		}
+		while (st != NULL) {
+			if (st->len > ol) {
+				p = st->ptr + ol;
+				l = st->len - ol;
+				len += l;
+				break;
+			}
+			ol -= st->len;
+			assert(ol >= 0);
+			nl -= st->len;
+			assert(nl > 0);
+			sl += st->len;
+			st = VTAILQ_NEXT(st, list);
+			if (VTAILQ_NEXT(st, list) != NULL) {
+				checkpoint = st;
+				checkpoint_len = sl;
+			}
+		}
+		CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
+		CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
+		st = VTAILQ_NEXT(st, list);
+		if (st != NULL && st->len == 0)
+			st = NULL;
+		Lck_Unlock(&bo->mtx);
+		assert(l > 0 || bo->state == BOS_FINISHED);
+		if (func(priv, st != NULL ? 0 : 1, p, l)) {
+			ret = -1;
+			break;
+		}
+	}
+	if (oc->flags & OC_F_PASS)
+		bo->abandon = 1;
+	VBO_DerefBusyObj(wrk, &bo);
+	return (ret);
+}
+
+/*--------------------------------------------------------------------
+ */
+
+static struct storage *
+objallocwithnuke(struct worker *wrk, const struct stevedore *stv, size_t size)
+{
+	struct storage *st = NULL;
+	unsigned fail;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
+
+	if (size > cache_param->fetch_maxchunksize)
+		size = cache_param->fetch_maxchunksize;
+
+	assert(size <= UINT_MAX);	/* field limit in struct storage */
+
+	for (fail = 0; fail <= cache_param->nuke_limit; fail++) {
+		/* try to allocate from it */
+		AN(stv->alloc);
+		st = STV_alloc(stv, size);
+		if (st != NULL)
+			break;
+
+		/* no luck; try to free some space and keep trying */
+		if (fail < cache_param->nuke_limit &&
+		    EXP_NukeOne(wrk, stv->lru) == -1)
+			break;
+	}
+	CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
+	return (st);
+}
+
+static int __match_proto__(objgetspace_f)
+sml_getspace(struct worker *wrk, struct objcore *oc, ssize_t *sz,
+    uint8_t **ptr)
+{
+	struct object *o;
+	struct storage *st;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	AN(sz);
+	AN(ptr);
+	assert(*sz > 0);
+
+	o = getobj(wrk, oc);
+	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
+
+	st = VTAILQ_LAST(&o->list, storagehead);
+	if (st != NULL && st->len < st->space) {
+		*sz = st->space - st->len;
+		*ptr = st->ptr + st->len;
+		assert (*sz > 0);
+		return (1);
+	}
+
+	st = objallocwithnuke(wrk, oc->stobj->stevedore, *sz);
+	if (st == NULL)
+		return (0);
+
+	if (oc->busyobj != NULL) {
+		CHECK_OBJ_NOTNULL(oc->busyobj, BUSYOBJ_MAGIC);
+		Lck_Lock(&oc->busyobj->mtx);
+		VTAILQ_INSERT_TAIL(&o->list, st, list);
+		Lck_Unlock(&oc->busyobj->mtx);
+	} else {
+		AN(oc->flags & (OC_F_PRIVATE));
+		VTAILQ_INSERT_TAIL(&o->list, st, list);
+	}
+	*sz = st->space - st->len;
+	assert (*sz > 0);
+	*ptr = st->ptr + st->len;
+	return (1);
+}
+
+static void __match_proto__(objextend_f)
+sml_extend(struct worker *wrk, struct objcore *oc, ssize_t l)
+{
+	struct object *o;
+	struct storage *st;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	assert(l > 0);
+
+	o = getobj(wrk, oc);
+	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
+	st = VTAILQ_LAST(&o->list, storagehead);
+	CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
+	assert(st->len + l <= st->space);
+	st->len += l;
+	o->len += l;
+}
+
+static uint64_t __match_proto__(objgetlen_f)
+sml_getlen(struct worker *wrk, struct objcore *oc)
+{
+	struct object *o;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+
+	o = getobj(wrk, oc);
+	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
+	return (o->len);
+}
+
+static void __match_proto__(objtrimstore_f)
+sml_trimstore(struct worker *wrk, struct objcore *oc)
+{
+	const struct stevedore *stv;
+	struct storage *st;
+	struct object *o;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+
+	stv = oc->stobj->stevedore;
+	CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
+	o = getobj(wrk, oc);
+	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
+	st = VTAILQ_LAST(&o->list, storagehead);
+	if (st == NULL)
+		return;
+	if (st->len == 0) {
+		VTAILQ_REMOVE(&o->list, st, list);
+		STV_free(stv, st);
+	} else if (st->len < st->space) {
+		STV_trim(stv, st, st->len, 1);
+	}
+}
+
+static void __match_proto__(objslim_f)
+sml_slim(struct worker *wrk, struct objcore *oc)
+{
+	const struct stevedore *stv;
+	struct object *o;
+	struct storage *st, *stn;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+
+	stv = oc->stobj->stevedore;
+	CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
+	o = getobj(wrk, oc);
+	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
+
+	if (o->esidata != NULL) {
+		STV_free(stv, o->esidata);
+		o->esidata = NULL;
+	}
+	VTAILQ_FOREACH_SAFE(st, &o->list, list, stn) {
+		CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
+		VTAILQ_REMOVE(&o->list, st, list);
+		STV_free(stv, st);
+	}
+}
+
+static void * __match_proto__(objgetattr_f)
+sml_getattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
+   ssize_t *len)
+{
+	struct object *o;
+	ssize_t dummy;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+
+	if (len == NULL)
+		len = &dummy;
+	o = getobj(wrk, oc);
+	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
+	switch (attr) {
+	case OA_ESIDATA:
+		if (o->esidata == NULL)
+			return (NULL);
+		*len = o->esidata->len;
+		return (o->esidata->ptr);
+	case OA_FLAGS:
+		*len = sizeof o->oa_flags;
+		return (o->oa_flags);
+	case OA_GZIPBITS:
+		*len = sizeof o->oa_gzipbits;
+		return (o->oa_gzipbits);
+	case OA_HEADERS:
+		*len = 0;			// XXX: hack
+		return (o->oa_http);
+	case OA_LASTMODIFIED:
+		*len = sizeof o->oa_lastmodified;
+		return (o->oa_lastmodified);
+	case OA_VARY:
+		*len = 4;			// XXX: hack
+		return (o->oa_vary);
+	case OA_VXID:
+		*len = sizeof o->oa_vxid;
+		return (o->oa_vxid);
+	default:
+		break;
+	}
+	WRONG("Unsupported OBJ_ATTR");
+}
+
+static void * __match_proto__(objsetattr_f)
+sml_setattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
+    ssize_t len, const void *ptr)
+{
+	struct object *o;
+	void *retval = NULL;
+	struct storage *st;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+
+	o = getobj(wrk, oc);
+	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
+	st = o->objstore;
+	switch (attr) {
+	case OA_ESIDATA:
+		o->esidata = objallocwithnuke(wrk, oc->stobj->stevedore, len);
+		if (o->esidata == NULL)
+			return (NULL);
+		o->esidata->len = len;
+		retval  = o->esidata->ptr;
+		break;
+	case OA_FLAGS:
+		assert(len == sizeof o->oa_flags);
+		retval = o->oa_flags;
+		break;
+	case OA_GZIPBITS:
+		assert(len == sizeof o->oa_gzipbits);
+		retval = o->oa_gzipbits;
+		break;
+	case OA_HEADERS:
+		len = PRNDUP(len);
+		assert(st->len + len <= st->space);
+		o->oa_http = (void*)(st->ptr + st->len);
+		st->len += len;
+		retval = o->oa_http;
+		break;
+	case OA_LASTMODIFIED:
+		assert(len == sizeof o->oa_lastmodified);
+		retval = o->oa_lastmodified;
+		break;
+	case OA_VARY:
+		len = PRNDUP(len);
+		assert(st->len + len <= st->space);
+		o->oa_vary = (void*)(st->ptr + st->len);
+		st->len += len;
+		retval = o->oa_vary;
+		break;
+	case OA_VXID:
+		assert(len == sizeof o->oa_vxid);
+		retval = o->oa_vxid;
+		break;
+	default:
+		WRONG("Unsupported OBJ_ATTR");
+		break;
+	}
+	if (ptr != NULL)
+		memcpy(retval, ptr, len);
+	return (retval);
+}
+
+
+const struct storeobj_methods SML_methods = {
+	.objfree	= sml_objfree,
+	.objgetlru	= sml_objgetlru,
+	.objiterator	= sml_iterator,
+	.objgetspace	= sml_getspace,
+	.objextend	= sml_extend,
+	.objgetlen	= sml_getlen,
+	.objtrimstore	= sml_trimstore,
+	.objslim	= sml_slim,
+	.objgetattr	= sml_getattr,
+	.objsetattr	= sml_setattr,
 };
diff --git a/bin/varnishd/storage/storage_simple.h b/bin/varnishd/storage/storage_simple.h
new file mode 100644
index 0000000..b199e7a
--- /dev/null
+++ b/bin/varnishd/storage/storage_simple.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * 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.
+ *
+ * SML is a set of methods for simple stevedores which just do simple
+ * memory allocation and leave all the high-level stuff to SML.
+ *
+ */
+
+/* Object ------------------------------------------------------------*/
+
+VTAILQ_HEAD(storagehead, storage);
+
+struct object {
+	unsigned		magic;
+#define OBJECT_MAGIC		0x32851d42
+	struct storage		*objstore;
+
+	char			oa_vxid[4];
+	uint8_t			*oa_vary;
+	uint8_t			*oa_http;
+	uint8_t			oa_flags[1];
+	char			oa_gzipbits[32];
+	char			oa_lastmodified[8];
+
+	struct storagehead	list;
+	ssize_t			len;
+
+	struct storage		*esidata;
+};
+
+extern const struct storeobj_methods SML_methods;
+
+struct object *SML_MkObject(const struct stevedore *, struct objcore *,
+    void *ptr);
+
+storage_allocobj_f SML_allocobj;
+
diff --git a/bin/varnishd/storage/storage_umem.c b/bin/varnishd/storage/storage_umem.c
index eb194aa..aa268ec 100644
--- a/bin/varnishd/storage/storage_umem.c
+++ b/bin/varnishd/storage/storage_umem.c
@@ -41,6 +41,7 @@
 
 #include "cache/cache.h"
 #include "storage/storage.h"
+#include "storage/storage_simple.h"
 
 static size_t			smu_max = SIZE_MAX;
 static MTX			smu_mtx;
@@ -161,7 +162,8 @@ const struct stevedore smu_stevedore = {
 	.alloc		=	smu_alloc,
 	.free		=	smu_free,
 	.trim		=	smu_trim,
-	.methods	=	&default_oc_methods,
+	.allocobj	=	SML_allocobj,
+	.methods	=	&SML_methods,
 };
 
 #endif /* HAVE_UMEM_H */



More information about the varnish-commit mailing list