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