[Mesa-dev] [PATCH 7/7] glsl/cache: Write newly cached files atomically via rename()
Carl Worth
cworth at cworth.org
Wed Feb 4 13:53:01 PST 2015
Instead of writing directly to the desired <filename>, with this patch
we instead first write to <filename>.tmp and then use rename() to
atomically rename from <filename>.tmp to <filename>. This ensures that
any process that opens <filename> for reading will never see any
partially written file.
---
src/glsl/cache.c | 41 +++++++++++++++++++++++++----------------
1 file changed, 25 insertions(+), 16 deletions(-)
diff --git a/src/glsl/cache.c b/src/glsl/cache.c
index 0bbf659..e0cdc1a 100644
--- a/src/glsl/cache.c
+++ b/src/glsl/cache.c
@@ -323,9 +323,9 @@ cache_put(struct program_cache *cache,
uint32_t *s = (uint32_t *) key;
int i = *s & (INDEX_SIZE - 1);
unsigned char *entry;
- int fd, ret;
+ int fd = -1, ret;
size_t len;
- char *filename;
+ char *filename = NULL, *filename_tmp = NULL;
const char *p = (const char *) data;
/* FIXME: We'll need an fsync here and think about races... maybe even need
@@ -336,40 +336,49 @@ cache_put(struct program_cache *cache,
entry = &cache->index[i * CACHE_KEY_SIZE];
filename = get_cache_file(cache, entry);
if (filename == NULL)
- return;
+ goto done;
unlink(filename);
ralloc_free(filename);
+ filename = NULL;
memcpy(entry, key, CACHE_KEY_SIZE);
if (data == NULL)
- return;
-
- /* FIXME: We should write the file to a name like <sha1>-foo, close it and
- * then rename(2) it to <sha1> to make sure some other mesa process doesn't
- * open it and gets a partial result. Racing with another mesa writing the
- * same file is ok, since they'll both write the same contents, and whoever
- * finishes first will move the complete file in place. */
+ goto done;
filename = get_cache_file(cache, key);
if (filename == NULL)
- return;
+ goto done;
- fd = open(filename, O_WRONLY | O_CLOEXEC | O_CREAT, 0644);
- ralloc_free(filename);
+ filename_tmp = ralloc_asprintf(cache, "%s.tmp", filename);
+ if (filename_tmp == NULL)
+ goto done;
+
+ fd = open(filename_tmp, O_WRONLY | O_CLOEXEC | O_CREAT, 0644);
if (fd == -1)
- return;
+ goto done;
for (len = 0; len < size; len += ret) {
ret = write(fd, p + len, size - len);
if (ret == -1) {
- unlink(filename);
- break;
+ unlink(filename_tmp);
+ goto done;
}
}
close(fd);
+ fd = -1;
+
+ rename(filename_tmp, filename);
+
+ done:
+ if (filename_tmp)
+ ralloc_free(filename_tmp);
+ if (filename)
+ ralloc_free(filename);
+ if (fd != -1)
+ close(fd);
}
void
--
2.1.4
More information about the mesa-dev
mailing list