Commit b4f9d546 authored by Martin Blix Grydeland's avatar Martin Blix Grydeland

Add a VSL_Check function to check a record pointers validity.

Introduce a VSLC_ptr type to represent a record pointer.
parent 64ad5841
......@@ -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);
......
......@@ -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.
......
......@@ -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[];
};
......
......@@ -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],
......
......@@ -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 {
......
......@@ -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));
}
......@@ -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);
......
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment