[PATCH 05/10] Sync the segment list in smp_thread().
Martin Blix Grydeland
martin at varnish-software.com
Wed Oct 10 16:27:18 CEST 2012
This allows us to avoid waiting for disk IO while holding the silo
mutex.
---
bin/varnishd/storage/storage_persistent.c | 67 +++++++++++++++++++++++-
bin/varnishd/storage/storage_persistent.h | 3 +-
bin/varnishd/storage/storage_persistent_silo.c | 66 ++++++-----------------
3 files changed, 83 insertions(+), 53 deletions(-)
diff --git a/bin/varnishd/storage/storage_persistent.c b/bin/varnishd/storage/storage_persistent.c
index 914de31..0575c11 100644
--- a/bin/varnishd/storage/storage_persistent.c
+++ b/bin/varnishd/storage/storage_persistent.c
@@ -342,6 +342,64 @@ smp_open_segs(struct smp_sc *sc, struct smp_signspace *spc)
}
/*--------------------------------------------------------------------
+ * Write the segmentlist back to the silo.
+ *
+ * We write the first copy, sync it synchronously, then write the
+ * second copy and sync it synchronously.
+ *
+ * Provided the kernel doesn't lie, that means we will always have
+ * at least one valid copy on in the silo.
+ */
+
+static void
+smp_save_segs(struct smp_sc *sc)
+{
+ struct smp_segptr *ss;
+ struct smp_seg *sg, *sg2;
+ uint64_t length;
+
+ Lck_AssertHeld(&sc->mtx);
+ sc->flags &= ~SMP_SC_SYNC;
+
+ /*
+ * Remove empty segments from the front of the list
+ * before we write the segments to disk.
+ */
+ VTAILQ_FOREACH_SAFE(sg, &sc->segments, list, sg2) {
+ if (sg->nobj > 0)
+ break;
+ if (sg == sc->cur_seg)
+ continue;
+ VTAILQ_REMOVE(&sc->segments, sg, list);
+ LRU_Free(sg->lru);
+ FREE_OBJ(sg);
+ }
+
+ Lck_Unlock(&sc->mtx);
+ AZ(smp_chk_signspace(&sc->seg1)); /* Page in */
+ smp_reset_signspace(&sc->seg1);
+ Lck_Lock(&sc->mtx);
+
+ /* First write to seg1 while holding lock */
+ ss = SIGNSPACE_FRONT(&sc->seg1);
+ length = 0;
+ VTAILQ_FOREACH(sg, &sc->segments, list) {
+ assert(sg->p.offset < sc->mediasize);
+ assert(sg->p.offset + sg->p.length <= sc->mediasize);
+ *ss = sg->p;
+ ss++;
+ length += sizeof *ss;
+ }
+
+ Lck_Unlock(&sc->mtx);
+ smp_append_signspace(&sc->seg1, length);
+ smp_sync_sign(&sc->seg1.ctx); /* Sync without lock */
+ /* Copy seg1 to seg2 */
+ smp_copy_signspace(&sc->seg2, &sc->seg1);
+ smp_sync_sign(&sc->seg2.ctx);
+ Lck_Lock(&sc->mtx);
+}
+/*--------------------------------------------------------------------
* Silo worker thread
*/
@@ -368,8 +426,7 @@ smp_thread(struct worker *wrk, void *priv)
/* Housekeeping loop */
Lck_Lock(&sc->mtx);
while (!(sc->flags & SMP_SC_STOP)) {
- sg = VTAILQ_FIRST(&sc->segments);
- if (sg != NULL && sg != sc->cur_seg && sg->nobj == 0)
+ if (sc->flags & SMP_SC_SYNC)
smp_save_segs(sc);
Lck_Unlock(&sc->mtx);
@@ -733,6 +790,12 @@ debug_persistent(struct cli *cli, const char * const * av, void *priv)
if (!strcmp(av[3], "sync")) {
if (sc->cur_seg != NULL)
smp_close_seg(sc, sc->cur_seg);
+ smp_sync_segs(sc);
+ while (sc->flags & SMP_SC_SYNC) {
+ Lck_Unlock(&sc->mtx);
+ VTIM_sleep(0.1);
+ Lck_Lock(&sc->mtx);
+ }
smp_new_seg(sc);
} else if (!strcmp(av[3], "dump")) {
debug_report_silo(cli, sc, 1);
diff --git a/bin/varnishd/storage/storage_persistent.h b/bin/varnishd/storage/storage_persistent.h
index c2cbac3..0c4e3a3 100644
--- a/bin/varnishd/storage/storage_persistent.h
+++ b/bin/varnishd/storage/storage_persistent.h
@@ -108,6 +108,7 @@ struct smp_sc {
unsigned flags;
#define SMP_SC_LOADED (1 << 0)
#define SMP_SC_STOP (1 << 1)
+#define SMP_SC_SYNC (1 << 2)
const struct stevedore *stevedore;
int fd;
@@ -194,7 +195,7 @@ void smp_load_seg(struct worker *, const struct smp_sc *sc, struct smp_seg *sg);
void smp_new_seg(struct smp_sc *sc);
void smp_close_seg(struct smp_sc *sc, struct smp_seg *sg);
void smp_init_oc(struct objcore *oc, struct smp_seg *sg, unsigned objidx);
-void smp_save_segs(struct smp_sc *sc);
+void smp_sync_segs(struct smp_sc *sc);
/* storage_persistent_subr.c */
diff --git a/bin/varnishd/storage/storage_persistent_silo.c b/bin/varnishd/storage/storage_persistent_silo.c
index 7ca79d6..fb384ee 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -48,59 +48,14 @@
#include "storage/storage_persistent.h"
/*--------------------------------------------------------------------
- * Write the segmentlist back to the silo.
- *
- * We write the first copy, sync it synchronously, then write the
- * second copy and sync it synchronously.
- *
- * Provided the kernel doesn't lie, that means we will always have
- * at least one valid copy on in the silo.
+ * Signal smp_thread() to sync the segment list to disk
*/
-static void
-smp_save_seg(const struct smp_sc *sc, struct smp_signspace *spc)
-{
- struct smp_segptr *ss;
- struct smp_seg *sg;
- uint64_t length;
-
- Lck_AssertHeld(&sc->mtx);
- smp_reset_signspace(spc);
- ss = SIGNSPACE_DATA(spc);
- length = 0;
- VTAILQ_FOREACH(sg, &sc->segments, list) {
- assert(sg->p.offset < sc->mediasize);
- assert(sg->p.offset + sg->p.length <= sc->mediasize);
- *ss = sg->p;
- ss++;
- length += sizeof *ss;
- }
- smp_append_signspace(spc, length);
- smp_sync_sign(&spc->ctx);
-}
-
void
-smp_save_segs(struct smp_sc *sc)
+smp_sync_segs(struct smp_sc *sc)
{
- struct smp_seg *sg, *sg2;
-
Lck_AssertHeld(&sc->mtx);
-
- /*
- * Remove empty segments from the front of the list
- * before we write the segments to disk.
- */
- VTAILQ_FOREACH_SAFE(sg, &sc->segments, list, sg2) {
- if (sg->nobj > 0)
- break;
- if (sg == sc->cur_seg)
- continue;
- VTAILQ_REMOVE(&sc->segments, sg, list);
- LRU_Free(sg->lru);
- FREE_OBJ(sg);
- }
- smp_save_seg(sc, &sc->seg1);
- smp_save_seg(sc, &sc->seg2);
+ sc->flags |= SMP_SC_SYNC;
}
/*--------------------------------------------------------------------
@@ -177,6 +132,12 @@ smp_new_seg(struct smp_sc *sc)
AZ(sc->cur_seg);
Lck_AssertHeld(&sc->mtx);
+ if (sc->flags & SMP_SC_STOP) {
+ /* Housekeeping thread is stopping, don't allow new
+ * segments as there is noone around to persist it */
+ return;
+ }
+
/* XXX: find where it goes in silo */
memset(&tmpsg, 0, sizeof tmpsg);
@@ -303,8 +264,8 @@ smp_close_seg(struct smp_sc *sc, struct smp_seg *sg)
smp_reset_sign(sg->ctx);
smp_sync_sign(sg->ctx);
- /* Save segment list */
- smp_save_segs(sc);
+ /* Request sync of segment list */
+ smp_sync_segs(sc);
sc->free_offset = smp_segend(sg);
}
@@ -524,6 +485,11 @@ smp_oc_freeobj(struct objcore *oc)
sg->nobj--;
sg->nfixed--;
+ if (sg->nobj == 0 && sg == VTAILQ_FIRST(&sg->sc->segments)) {
+ /* Sync segments to remove empty at start */
+ sg->sc->flags |= SMP_SC_SYNC;
+ }
+
Lck_Unlock(&sg->sc->mtx);
}
--
1.7.9.5
More information about the varnish-dev
mailing list