Commit 55e6b1c7 authored by Geoff Simmons's avatar Geoff Simmons

Narrow the scope of the exclusive lock.

The update check works on copies of the info struct, flags, etc.
Only take the write lock when all work is finished, then copy
data back under the lock.
parent 100beb7f
......@@ -52,9 +52,8 @@
#define VFAIL(ctx, fmt, ...) \
VRT_fail((ctx), "vmod file failure: " fmt, __VA_ARGS__)
#define VERRMSG(rdr, fmt, ...) \
snprintf((rdr)->errbuf, (rdr)->errlen, "vmod file failure: " fmt, \
__VA_ARGS__)
#define VERRMSG(rdr, buf, fmt, ...) \
snprintf((buf), (rdr)->errlen, "vmod file failure: " fmt, __VA_ARGS__)
/* Other VMODs may check the result of .blob() for this value, see vrt.h */
#define VMOD_FILE_BLOB_MAGIC 0x069392c4
......@@ -114,21 +113,34 @@ static void
check(union sigval val)
{
struct VPFX(file_reader) *rdr;
struct file_info *info;
struct file_info info[1];
struct stat st;
int fd = -1;
void *addr;
char timbuf[VTIM_FORMAT_SIZE];
int flags, fd = -1;
void *addr = NULL, *prev;
char timbuf[VTIM_FORMAT_SIZE], *errbuf = NULL;
int err;
VSHA256_CTX sha_ctx;
unsigned char sha256[VSHA256_DIGEST_LENGTH];
CAST_OBJ_NOTNULL(rdr, val.sival_ptr, FILE_READER_MAGIC);
CHECK_OBJ_NOTNULL(rdr->info, FILE_INFO_MAGIC);
info = rdr->info;
AN(rdr->vcl_name);
AN(rdr->obj_name);
AN(rdr->errbuf);
AN(info->path);
AN(rdr->info->path);
errno = 0;
errbuf = calloc(1, rdr->errlen);
if (errbuf == NULL) {
snprintf(rdr->errbuf, rdr->errlen, "vmod file failure: "
"cannot allocate temp err buffer");
VSL(SLT_Error, 0, "vmod file: cannot allocate temp err buffer");
rdr->flags |= RDR_ERROR;
return;
}
memcpy(info, rdr->info, sizeof(info));
flags = rdr->flags;
if (info->log_checks) {
VTIM_format(VTIM_real(), timbuf);
......@@ -137,44 +149,42 @@ check(union sigval val)
rdr->vcl_name, rdr->obj_name, info->path, timbuf);
}
AZ(pthread_rwlock_wrlock(&rdr->lock));
errno = 0;
if ((fd = open(info->path, O_RDONLY)) < 0) {
if (errno == ENOENT && (rdr->flags & RDR_MAPPED) != 0) {
rdr->flags |= RDR_DELETED;
if (errno == ENOENT && (flags & RDR_MAPPED) != 0) {
flags |= RDR_DELETED;
VSL(SLT_Debug, 0, "vmod file: %s.%s: %s is deleted but "
"already mapped", rdr->vcl_name, rdr->obj_name,
info->path);
goto out;
}
VERRMSG(rdr, "%s.%s: cannot open %s: %s", rdr->vcl_name,
VERRMSG(rdr, errbuf, "%s.%s: cannot open %s: %s", rdr->vcl_name,
rdr->obj_name, info->path, vstrerror(errno));
VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR;
VSL(SLT_Error, 0, errbuf);
flags |= RDR_ERROR;
goto out;
}
rdr->flags &= ~RDR_DELETED;
flags &= ~RDR_DELETED;
errno = 0;
if (fstat(fd, &st) != 0) {
VERRMSG(rdr, "%s.%s: cannot read info about %s: %s",
VERRMSG(rdr, errbuf, "%s.%s: cannot read info about %s: %s",
rdr->vcl_name, rdr->obj_name, info->path,
vstrerror(errno));
VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR;
VSL(SLT_Error, 0, errbuf);
flags |= RDR_ERROR;
goto out;
}
if (!S_ISREG(st.st_mode)) {
VERRMSG(rdr, "%s.%s: %s is not a regular file", rdr->vcl_name,
rdr->obj_name, info->path);
VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR;
VERRMSG(rdr, errbuf, "%s.%s: %s is not a regular file",
rdr->vcl_name, rdr->obj_name, info->path);
VSL(SLT_Error, 0, errbuf);
flags |= RDR_ERROR;
goto out;
}
if ((rdr->flags & (RDR_INITIALIZED | RDR_MAPPED))
if ((flags & (RDR_INITIALIZED | RDR_MAPPED))
&& info->mtime.tv_sec == st.st_mtim.tv_sec
&& info->mtime.tv_nsec == st.st_mtim.tv_nsec
&& info->dev == st.st_dev && info->ino == st.st_ino) {
......@@ -188,18 +198,6 @@ check(union sigval val)
rdr->vcl_name, rdr->obj_name, info->path, timbuf);
}
if (rdr->flags & RDR_MAPPED) {
AN(rdr->addr);
if (munmap(rdr->addr, info->len) != 0) {
VERRMSG(rdr, "%s.%s: unmap failed: %s", rdr->vcl_name,
rdr->obj_name, vstrerror(errno));
VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR;
goto out;
}
}
rdr->flags &= ~RDR_MAPPED;
/*
* By mapping the length st_size + 1, and due to the fact that
* mmap(2) fills the region of the mapped page past the length of
......@@ -211,37 +209,36 @@ check(union sigval val)
errno = 0;
if ((addr = mmap(NULL, st.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0))
== MAP_FAILED) {
VERRMSG(rdr, "%s.%s: could not map %s: %s", rdr->vcl_name,
rdr->obj_name, info->path, vstrerror(errno));
VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR;
VERRMSG(rdr, errbuf, "%s.%s: could not map %s: %s",
rdr->vcl_name, rdr->obj_name, info->path,
vstrerror(errno));
VSL(SLT_Error, 0, errbuf);
flags |= RDR_ERROR;
goto out;
}
AN(addr);
rdr->flags |= RDR_MAPPED;
if ((err = posix_madvise(addr, st.st_size + 1, POSIX_MADV_SEQUENTIAL))
!= 0) {
VERRMSG(rdr, "%s.%s: madvise(SEQUENTIAL): %s", rdr->vcl_name,
rdr->obj_name, vstrerror(err));
VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR;
VERRMSG(rdr, errbuf, "%s.%s: madvise(SEQUENTIAL): %s",
rdr->vcl_name, rdr->obj_name, vstrerror(err));
VSL(SLT_Error, 0, errbuf);
flags |= RDR_ERROR;
goto out;
}
if ((err = posix_madvise(addr, st.st_size + 1, POSIX_MADV_WILLNEED))
!= 0) {
VERRMSG(rdr, "%s.%s: madvise(WILLNEED): %s", rdr->vcl_name,
rdr->obj_name, vstrerror(err));
VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR;
VERRMSG(rdr, errbuf, "%s.%s: madvise(WILLNEED): %s",
rdr->vcl_name, rdr->obj_name, vstrerror(err));
VSL(SLT_Error, 0, errbuf);
flags |= RDR_ERROR;
goto out;
}
if (info->sha256 != NULL) {
AN(info->sha256);
VSHA256_Init(&sha_ctx);
VSHA256_Update(&sha_ctx, addr, st.st_size);
VSHA256_Final(info->sha256, &sha_ctx);
VSHA256_Final(sha256, &sha_ctx);
}
info->mtime.tv_sec = st.st_mtim.tv_sec;
......@@ -250,14 +247,42 @@ check(union sigval val)
info->ino = st.st_ino;
info->len = st.st_size + 1;
rdr->addr = addr;
rdr->flags &= ~RDR_ERROR;
strcpy(rdr->errbuf, NO_ERR);
rdr->flags |= RDR_INITIALIZED;
flags &= ~RDR_ERROR;
flags |= RDR_INITIALIZED;
out:
AZ(pthread_rwlock_wrlock(&rdr->lock));
if (addr != NULL) {
prev = rdr->addr;
rdr->addr = addr;
flags |= RDR_MAPPED;
if (rdr->flags & RDR_MAPPED) {
AN(prev);
errno = 0;
if (munmap(prev, rdr->info->len) != 0) {
VERRMSG(rdr, errbuf, "%s.%s: unmap failed: %s",
rdr->vcl_name, rdr->obj_name,
vstrerror(errno));
VSL(SLT_Error, 0, errbuf);
flags |= RDR_ERROR;
}
}
}
if ((flags & RDR_ERROR) == 0) {
strcpy(rdr->errbuf, NO_ERR);
}
else
strcpy(rdr->errbuf, errbuf);
rdr->flags = flags;
memcpy(rdr->info, info, sizeof(*rdr->info));
if (rdr->info->sha256 != NULL)
memcpy(rdr->info->sha256, sha256, VSHA256_DIGEST_LENGTH);
AZ(pthread_rwlock_unlock(&rdr->lock));
free(errbuf);
if (fd != -1)
closefd(&fd);
......
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