[master] b4f9d54 Add a VSL_Check function to check a record pointers validity.
Martin Blix Grydeland
martin at varnish-cache.org
Wed May 15 14:46:14 CEST 2013
commit b4f9d54697eb54a0eae60b106eb7962824bcf97a
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date: Wed May 1 17:32:03 2013 +0200
Add a VSL_Check function to check a record pointers validity.
Introduce a VSLC_ptr type to represent a record pointer.
diff --git a/bin/varnishtest/vtc_varnish.c b/bin/varnishtest/vtc_varnish.c
index 64b24b8..80f9674 100644
--- a/bin/varnishtest/vtc_varnish.c
+++ b/bin/varnishtest/vtc_varnish.c
@@ -227,12 +227,12 @@ varnishlog_thread(void *priv)
} else if (i != 1)
break;
- tag = VSL_TAG(c->ptr);
- vxid = VSL_ID(c->ptr);
- len = VSL_LEN(c->ptr);
- type = VSL_CLIENT(c->ptr) ? 'c' : VSL_BACKEND(c->ptr) ?
+ tag = VSL_TAG(c->rec.ptr);
+ vxid = VSL_ID(c->rec.ptr);
+ len = VSL_LEN(c->rec.ptr);
+ type = VSL_CLIENT(c->rec.ptr) ? 'c' : VSL_BACKEND(c->rec.ptr) ?
'b' : '-';
- data = VSL_CDATA(c->ptr);
+ data = VSL_CDATA(c->rec.ptr);
v->vsl_tag_count[tag]++;
vtc_log(v->vl, 4, "vsl| %10u %-15s %c %.*s", vxid,
VSL_tags[tag], type, (int)len, data);
diff --git a/include/vapi/vsl.h b/include/vapi/vsl.h
index 023b65f..4bb1d60 100644
--- a/include/vapi/vsl.h
+++ b/include/vapi/vsl.h
@@ -51,8 +51,14 @@
struct VSL_data;
struct VSLQ;
-struct VSL_cursor {
+struct VSLC_ptr {
const uint32_t *ptr; /* Record pointer */
+ unsigned priv;
+};
+
+struct VSL_cursor {
+ /* The record this cursor points to */
+ struct VSLC_ptr rec;
/* If not -1, the vxid of all records in this set */
int32_t vxid;
@@ -151,6 +157,18 @@ int VSL_ResetCursor(struct VSL_cursor *c);
* -1: Operation not supported
*/
+int VSL_Check(const struct VSL_cursor *c, const struct VSLC_ptr *ptr);
+ /*
+ * Check if the VSLC_ptr structure points to a value that is still
+ * valid:
+ *
+ * Return values:
+ * -1: Operation not supported
+ * 0: Not valid
+ * 1: Valid - warning level
+ * 2: Valid
+ */
+
int VSL_Next(struct VSL_cursor *c);
/*
* Return raw pointer to next VSL record.
diff --git a/include/vapi/vsl_int.h b/include/vapi/vsl_int.h
index c42198a..f65dc9f 100644
--- a/include/vapi/vsl_int.h
+++ b/include/vapi/vsl_int.h
@@ -68,9 +68,9 @@
struct VSL_head {
#define VSL_HEAD_MARKER "VSLHEAD0" /* Incr. as version# */
char marker[VSM_MARKER_LEN];
- ssize_t segments[VSL_SEGMENTS];
- unsigned segment; /* Current varnishd segment */
- unsigned seq; /* Non-zero seq number */
+ volatile ssize_t segments[VSL_SEGMENTS];
+ volatile unsigned segment; /* Current varnishd segment */
+ volatile unsigned seq; /* Non-zero seq number */
uint32_t log[];
};
diff --git a/lib/libvarnishapi/vsl.c b/lib/libvarnishapi/vsl.c
index 994d76d..25e1898 100644
--- a/lib/libvarnishapi/vsl.c
+++ b/lib/libvarnishapi/vsl.c
@@ -140,9 +140,9 @@ VSL_Match(struct VSL_data *vsl, const struct VSL_cursor *c)
enum VSL_tag_e tag;
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
- if (c == NULL || c->ptr == NULL)
+ if (c == NULL || c->rec.ptr == NULL)
return (0);
- tag = VSL_TAG(c->ptr);
+ tag = VSL_TAG(c->rec.ptr);
if (tag <= SLT__Bogus || tag >= SLT__Reserved)
return (0);
if (vbit_test(vsl->vbm_select, tag))
@@ -165,15 +165,16 @@ VSL_PrintVXID(struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
int i;
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
- if (c == NULL || c->ptr == NULL)
+ if (c == NULL || c->rec.ptr == NULL)
return (0);
if (fo == NULL)
fo = stdout;
- tag = VSL_TAG(c->ptr);
- vxid = VSL_ID(c->ptr);
- len = VSL_LEN(c->ptr);
- type = VSL_CLIENT(c->ptr) ? 'c' : VSL_BACKEND(c->ptr) ? 'b' : '-';
- data = VSL_CDATA(c->ptr);
+ tag = VSL_TAG(c->rec.ptr);
+ vxid = VSL_ID(c->rec.ptr);
+ len = VSL_LEN(c->rec.ptr);
+ type = VSL_CLIENT(c->rec.ptr) ? 'c' : VSL_BACKEND(c->rec.ptr) ?
+ 'b' : '-';
+ data = VSL_CDATA(c->rec.ptr);
if (tag == SLT_Debug) {
i = fprintf(fo, "%10u %-15s %c \"", vxid, VSL_tags[tag], type);
@@ -211,15 +212,16 @@ VSL_PrintLevel(struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
int i;
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
- if (c == NULL || c->ptr == NULL)
+ if (c == NULL || c->rec.ptr == NULL)
return (0);
if (fo == NULL)
fo = stdout;
- tag = VSL_TAG(c->ptr);
- len = VSL_LEN(c->ptr);
- type = VSL_CLIENT(c->ptr) ? 'c' : VSL_BACKEND(c->ptr) ? 'b' : '-';
- data = VSL_CDATA(c->ptr);
+ tag = VSL_TAG(c->rec.ptr);
+ len = VSL_LEN(c->rec.ptr);
+ type = VSL_CLIENT(c->rec.ptr) ? 'c' : VSL_BACKEND(c->rec.ptr) ?
+ 'b' : '-';
+ data = VSL_CDATA(c->rec.ptr);
lvl = c->level;
if (tag == SLT_Debug) {
i = fprintf(fo, "%2u %-15s %c \"", lvl, VSL_tags[tag],
diff --git a/lib/libvarnishapi/vsl_api.h b/lib/libvarnishapi/vsl_api.h
index a03aef7..039d57b 100644
--- a/lib/libvarnishapi/vsl_api.h
+++ b/lib/libvarnishapi/vsl_api.h
@@ -35,6 +35,11 @@
#define VSL_FILE_HEAD "VSL"
+struct vslc_shmptr {
+ uint32_t *ptr;
+ unsigned priv;
+};
+
int vsl_diag(struct VSL_data *vsl, const char *fmt, ...)
__printflike(2, 3);
int vsl_skip(struct VSL_cursor *c, ssize_t words);
@@ -43,6 +48,8 @@ typedef void vslc_delete_f(void *);
typedef int vslc_next_f(void *);
typedef int vslc_reset_f(void *);
typedef int vslc_skip_f(void *, ssize_t words);
+typedef int vslc_ref_f(void *, struct vslc_shmptr *ptr);
+typedef int vslc_check_f(const void *, const struct VSLC_ptr *ptr);
struct vslc {
struct VSL_cursor c;
@@ -53,6 +60,7 @@ struct vslc {
vslc_next_f *next;
vslc_reset_f *reset;
vslc_skip_f *skip;
+ vslc_check_f *check;
};
struct VSL_data {
diff --git a/lib/libvarnishapi/vsl_cursor.c b/lib/libvarnishapi/vsl_cursor.c
index bf4d1ec..1712ade 100644
--- a/lib/libvarnishapi/vsl_cursor.c
+++ b/lib/libvarnishapi/vsl_cursor.c
@@ -55,11 +55,10 @@ struct vslc_vsm {
struct VSM_data *vsm;
struct VSM_fantom vf;
- volatile const struct VSL_head *head;
- volatile const uint32_t *next;
+ const struct VSL_head *head;
const uint32_t *end;
ssize_t segsize;
- unsigned seq;
+ struct VSLC_ptr next;
};
static void
@@ -72,74 +71,101 @@ vslc_vsm_delete(void *cursor)
}
static int
-vslc_vsm_next(void *cursor)
+vslc_vsm_check(const void *cursor, const struct VSLC_ptr *ptr)
{
- struct vslc_vsm *c;
- int diff;
- unsigned segment;
- uint32_t t;
+ const struct vslc_vsm *c;
+ unsigned seqdiff, segment, segdiff;
CAST_OBJ_NOTNULL(c, cursor, VSLC_VSM_MAGIC);
- CHECK_OBJ_NOTNULL(c->vsm, VSM_MAGIC);
- /* Assert pointers */
- AN(c->next);
- assert(c->next >= c->head->log);
- assert(c->next < c->end);
+ if (ptr->ptr == NULL)
+ return (0);
/* Check sequence number */
- diff = c->head->seq - c->seq;
- if (c->head->seq < c->seq)
+ seqdiff = c->head->seq - ptr->priv;
+ if (c->head->seq < ptr->priv)
/* Wrap around skips 0 */
- diff -= 1;
- if (diff > 1)
- return (-3);
+ seqdiff -= 1;
+ if (seqdiff > 1)
+ /* Too late */
+ return (0);
/* Check overrun */
- segment = (c->next - c->head->log) / c->segsize;
+ segment = (ptr->ptr - c->head->log) / c->segsize;
if (segment >= VSL_SEGMENTS)
+ /* Rounding error spills to last segment */
segment = VSL_SEGMENTS - 1;
- diff = (segment - c->head->segment) % VSL_SEGMENTS;
- if (0 < diff && diff <= 2)
+ segdiff = (segment - c->head->segment) % VSL_SEGMENTS;
+ if (segdiff == 0 && seqdiff == 0)
+ /* In same segment, but close to tail */
+ return (2);
+ if (segdiff <= 2)
+ /* Too close to continue */
+ return (0);
+ if (segdiff <= 4)
+ /* Warning level */
+ return (1);
+ /* Safe */
+ return (2);
+}
+
+static int
+vslc_vsm_next(void *cursor)
+{
+ struct vslc_vsm *c;
+ int i;
+ uint32_t t;
+
+ CAST_OBJ_NOTNULL(c, cursor, VSLC_VSM_MAGIC);
+ CHECK_OBJ_NOTNULL(c->vsm, VSM_MAGIC);
+
+ /* Assert pointers */
+ AN(c->next.ptr);
+ assert(c->next.ptr >= c->head->log);
+ assert(c->next.ptr < c->end);
+
+ i = vslc_vsm_check(c, &c->next);
+ if (i <= 0)
+ /* Overrun */
return (-3);
/* Check VSL fantom and abandonment */
- if (*c->next == VSL_ENDMARKER) {
+ if (*(volatile const uint32_t *)c->next.ptr == VSL_ENDMARKER) {
if (!VSM_StillValid(c->vsm, &c->vf) ||
VSM_Abandoned(c->vsm))
return (-2);
}
while (1) {
- assert(c->next >= c->head->log);
- assert(c->next < c->end);
+ assert(c->next.ptr >= c->head->log);
+ assert(c->next.ptr < c->end);
AN(c->head->seq);
- t = *c->next;
+ t = *(volatile const uint32_t *)c->next.ptr;
AN(t);
if (t == VSL_WRAPMARKER) {
/* Wrap around not possible at front */
- assert(c->next != c->head->log);
- c->next = c->head->log;
+ assert(c->next.ptr != c->head->log);
+ c->next.ptr = c->head->log;
continue;
}
if (t == VSL_ENDMARKER) {
- if (c->next != c->head->log &&
- c->seq != c->head->seq) {
+ if (c->next.ptr != c->head->log &&
+ c->next.priv != c->head->seq) {
/* ENDMARKER not at front and seq wrapped */
/* XXX: assert on this? */
- c->next = c->head->log;
+ c->next.ptr = c->head->log;
continue;
}
return (0);
}
- if (c->next == c->head->log)
- c->seq = c->head->seq;
+ if (c->next.ptr == c->head->log)
+ c->next.priv = c->head->seq;
- c->c.c.ptr = (void*)(uintptr_t)c->next; /* Loose volatile */
- c->next = VSL_NEXT(c->next);
+ c->c.c.rec = c->next;
+ c->next.ptr = VSL_NEXT(c->next.ptr);
return (1);
}
}
@@ -162,9 +188,9 @@ vslc_vsm_reset(void *cursor)
if (c->head->segments[segment] < 0)
segment = 0;
assert(c->head->segments[segment] >= 0);
- c->next = c->head->log + c->head->segments[segment];
- c->seq = c->head->seq;
- c->c.c.ptr = NULL;
+ c->next.ptr = c->head->log + c->head->segments[segment];
+ c->next.priv = c->head->seq;
+ c->c.c.rec.ptr = NULL;
return (0);
}
@@ -178,10 +204,10 @@ vslc_vsm_skip(void *cursor, ssize_t words)
if (words < 0)
return (-1);
- c->next += words;
- assert(c->next >= c->head->log);
- assert(c->next < c->end);
- c->c.c.ptr = NULL;
+ c->next.ptr += words;
+ assert(c->next.ptr >= c->head->log);
+ assert(c->next.ptr < c->end);
+ c->c.c.rec.ptr = NULL;
return (0);
}
@@ -223,6 +249,7 @@ VSL_CursorVSM(struct VSL_data *vsl, struct VSM_data *vsm, int tail)
c->c.next = vslc_vsm_next;
c->c.reset = vslc_vsm_reset;
c->c.skip = vslc_vsm_skip;
+ c->c.check = vslc_vsm_check;
c->vsm = vsm;
c->vf = vf;
@@ -232,10 +259,12 @@ VSL_CursorVSM(struct VSL_data *vsl, struct VSM_data *vsm, int tail)
if (tail) {
/* Locate tail of log */
- c->next = c->head->log + c->head->segments[c->head->segment];
- while (c->next < c->end && *c->next != VSL_ENDMARKER)
- c->next = VSL_NEXT(c->next);
- c->seq = c->head->seq;
+ c->next.ptr = c->head->log +
+ c->head->segments[c->head->segment];
+ while (c->next.ptr < c->end &&
+ *(volatile const uint32_t *)c->next.ptr != VSL_ENDMARKER)
+ c->next.ptr = VSL_NEXT(c->next.ptr);
+ c->next.priv = c->head->seq;
} else
AZ(vslc_vsm_reset(&c->c));
@@ -293,7 +322,7 @@ vslc_file_next(void *cursor)
return (c->error);
do {
- c->c.c.ptr = NULL;
+ c->c.c.rec.ptr = NULL;
assert(c->buflen >= 2 * 4);
i = vslc_file_readn(c->fd, c->buf, 2 * 4);
if (i < 0)
@@ -313,8 +342,9 @@ vslc_file_next(void *cursor)
if (i == 0)
return (-1); /* EOF */
assert(i == l - 2 * 4);
- c->c.c.ptr = c->buf;
- } while (c->c.c.ptr != NULL && VSL_TAG(c->c.c.ptr) == SLT__Batch);
+ c->c.c.rec.ptr = c->buf;
+ } while (c->c.c.rec.ptr != NULL &&
+ VSL_TAG(c->c.c.rec.ptr) == SLT__Batch);
return (1);
}
@@ -423,3 +453,14 @@ vsl_skip(struct VSL_cursor *cursor, ssize_t words)
return (-1);
return ((c->skip)(c, words));
}
+
+int
+VSL_Check(const struct VSL_cursor *cursor, const struct VSLC_ptr *ptr)
+{
+ const struct vslc *c;
+
+ CAST_OBJ_NOTNULL(c, (const void *)cursor, VSLC_MAGIC);
+ if (c->check == NULL)
+ return (-1);
+ return ((c->check)(c, ptr));
+}
diff --git a/lib/libvarnishapi/vsl_dispatch.c b/lib/libvarnishapi/vsl_dispatch.c
index 61b0518..c5389b9 100644
--- a/lib/libvarnishapi/vsl_dispatch.c
+++ b/lib/libvarnishapi/vsl_dispatch.c
@@ -181,7 +181,7 @@ vslc_raw_next(void *cursor)
assert(c->next >= c->start);
assert(c->next <= c->start + c->len);
if (c->next < c->start + c->len) {
- c->c.c.ptr = c->next;
+ c->c.c.rec.ptr = c->next;
c->next = VSL_NEXT(c->next);
return (1);
}
@@ -198,7 +198,7 @@ vslc_raw_reset(void *cursor)
assert(c->next >= c->start);
assert(c->next <= c->start + c->len);
c->next = c->start;
- c->c.c.ptr = NULL;
+ c->c.c.rec.ptr = NULL;
return (0);
}
@@ -213,7 +213,7 @@ vslc_vtx_next(void *cursor)
assert(c->next >= c->vtx->start);
assert(c->next <= c->vtx->start + c->vtx->len);
if (c->next < c->vtx->start + c->vtx->len) {
- c->c.c.ptr = c->next;
+ c->c.c.rec.ptr = c->next;
c->next = VSL_NEXT(c->next);
return (1);
}
@@ -230,7 +230,7 @@ vslc_vtx_reset(void *cursor)
assert(c->next >= c->vtx->start);
assert(c->next <= c->vtx->start + c->vtx->len);
c->next = c->vtx->start;
- c->c.c.ptr = NULL;
+ c->c.c.rec.ptr = NULL;
return (0);
}
@@ -790,13 +790,13 @@ vslq_raw(struct VSLQ *vslq, VSLQ_dispatch_f *func, void *priv)
i = VSL_Next(c);
if (i <= 0)
break;
- AN(c->ptr);
+ AN(c->rec.ptr);
if (func == NULL)
continue;
- rawc.start = c->ptr;
- rawc.len = VSL_NEXT(c->ptr) - c->ptr;
+ rawc.start = c->rec.ptr;
+ rawc.len = VSL_NEXT(c->rec.ptr) - c->rec.ptr;
rawc.next = rawc.start;
- rawc.c.c.ptr = NULL;
+ rawc.c.c.rec.ptr = NULL;
/* Query check goes here */
i = 0;
@@ -831,13 +831,13 @@ VSLQ_Dispatch(struct VSLQ *vslq, VSLQ_dispatch_f *func, void *priv)
i = VSL_Next(c);
if (i != 1)
break;
- tag = VSL_TAG(c->ptr);
+ tag = VSL_TAG(c->rec.ptr);
if (tag == SLT__Batch) {
- ptr = VSL_NEXT(c->ptr);
- len = VSL_WORDS(c->ptr[1]);
+ ptr = VSL_NEXT(c->rec.ptr);
+ len = VSL_WORDS(c->rec.ptr[1]);
AZ(vsl_skip(c, len));
} else {
- ptr = c->ptr;
+ ptr = c->rec.ptr;
len = VSL_NEXT(ptr) - ptr;
}
vxid = VSL_ID(ptr);
diff --git a/lib/libvarnishapi/vsl_query.c b/lib/libvarnishapi/vsl_query.c
index b4a403c..852f8d3 100644
--- a/lib/libvarnishapi/vsl_query.c
+++ b/lib/libvarnishapi/vsl_query.c
@@ -104,9 +104,9 @@ vslq_runquery(struct vslq_query *query, struct VSL_cursor *cp[])
if (i == 0)
break;
assert(i == 1);
- AN(c->ptr);
- len = VSL_LEN(c->ptr);
- data = VSL_CDATA(c->ptr);
+ AN(c->rec.ptr);
+ len = VSL_LEN(c->rec.ptr);
+ data = VSL_CDATA(c->rec.ptr);
i = VRE_exec(query->regex, data, len, 0, 0, NULL, 0,
NULL);
if (i != VRE_ERROR_NOMATCH) {
More information about the varnish-commit
mailing list