util/disk_cache: add support for detecting corrupt cache entries
V2: fix pointer increments for writing/reading crc Acked-by: Marek Olšák <marek.olsak@amd.com> Reviewed-by: Grigori Goronzy <greg@chown.ath.cx>
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "util/crc32.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "util/mesa-sha1.h"
|
||||
#include "util/ralloc.h"
|
||||
@@ -709,6 +710,19 @@ disk_cache_put(struct disk_cache *cache,
|
||||
if (*cache->size + size > cache->max_size)
|
||||
evict_random_item(cache);
|
||||
|
||||
/* Create CRC of the data and store at the start of the file. We will
|
||||
* read this when restoring the cache and use it to check for corruption.
|
||||
*/
|
||||
uint32_t crc32 = util_hash_crc32(data, size);
|
||||
size_t crc_size = sizeof(crc32);
|
||||
for (len = 0; len < crc_size; len += ret) {
|
||||
ret = write(fd, ((uint8_t *) &crc32) + len, crc_size - len);
|
||||
if (ret == -1) {
|
||||
unlink(filename_tmp);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, finally, write out the contents to the temporary file, then
|
||||
* rename them atomically to the destination filename, and also
|
||||
* perform an atomic increment of the total cache size.
|
||||
@@ -723,6 +737,7 @@ disk_cache_put(struct disk_cache *cache,
|
||||
|
||||
rename(filename_tmp, filename);
|
||||
|
||||
size += crc_size;
|
||||
p_atomic_add(cache->size, size);
|
||||
|
||||
done:
|
||||
@@ -765,17 +780,33 @@ disk_cache_get(struct disk_cache *cache, cache_key key, size_t *size)
|
||||
if (data == NULL)
|
||||
goto fail;
|
||||
|
||||
for (len = 0; len < sb.st_size; len += ret) {
|
||||
ret = read(fd, data + len, sb.st_size - len);
|
||||
/* Load the CRC that was created when the file was written. */
|
||||
uint32_t crc32;
|
||||
size_t crc_size = sizeof(crc32);
|
||||
assert(sb.st_size > crc_size);
|
||||
for (len = 0; len < crc_size; len += ret) {
|
||||
ret = read(fd, ((uint8_t *) &crc32) + len, crc_size - len);
|
||||
if (ret == -1)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Load the actual cache data. */
|
||||
size_t cache_data_size = sb.st_size - crc_size;
|
||||
for (len = 0; len < cache_data_size; len += ret) {
|
||||
ret = read(fd, data + len, cache_data_size - len);
|
||||
if (ret == -1)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check the data for corruption */
|
||||
if (crc32 != util_hash_crc32(data, cache_data_size))
|
||||
goto fail;
|
||||
|
||||
free(filename);
|
||||
close(fd);
|
||||
|
||||
if (size)
|
||||
*size = sb.st_size;
|
||||
*size = cache_data_size;
|
||||
|
||||
return data;
|
||||
|
||||
|
Reference in New Issue
Block a user